diff --git a/Spigot-API-Patches/Add-minimal-fastutil-int-long-based-collections.patch b/Spigot-API-Patches/Add-minimal-fastutil-int-long-based-collections.patch
deleted file mode 100644
index 66b9abd6c9..0000000000
--- a/Spigot-API-Patches/Add-minimal-fastutil-int-long-based-collections.patch
+++ /dev/null
@@ -1,45209 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Aikar <aikar@aikar.co>
-Date: Mon, 21 Mar 2016 18:17:14 -0400
-Subject: [PATCH] Add minimal fastutil int/long based collections
-
-Importing entire FastUtil library would be massive. Just import minimal useful ones
-we might actually use.
-
-diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+/** An abstract class providing basic methods for implementing the {@link IndirectDoublePriorityQueue} interface.
-+ *
-+ * <P>This class defines  {@link #secondaryLast()} as throwing an
-+ * {@link UnsupportedOperationException}.
-+ */
-+
-+public abstract class AbstractIndirectDoublePriorityQueue<K> extends AbstractIndirectPriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
-+
-+	public int secondaryLast() { throw new UnsupportedOperationException(); }
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+/** An abstract class providing basic methods for implementing the {@link IndirectPriorityQueue} interface.
-+ *
-+ * <P>This class defines {@link #changed(int)}, {@link #allChanged()},  {@link #remove(int)} and {@link #last()} as throwing an
-+ * {@link UnsupportedOperationException}.
-+ */
-+
-+public abstract class AbstractIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
-+
-+	public int last() { throw new UnsupportedOperationException(); }
-+
-+	public void changed() { changed( first() ); }
-+	
-+	public void changed( int index ) { throw new UnsupportedOperationException(); }
-+
-+	public void allChanged() { throw new UnsupportedOperationException(); }
-+
-+	public boolean remove( int index ) { throw new UnsupportedOperationException(); }
-+
-+	public boolean contains( int index ) { throw new UnsupportedOperationException(); }
-+
-+	public boolean isEmpty() { return size() == 0; }
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+import it.unimi.dsi.fastutil.PriorityQueue;
-+
-+/**  An abstract class providing basic methods for implementing the {@link PriorityQueue} interface. 
-+ *
-+ * <P>This class defines {@link #changed()} and {@link #last()} as throwing an
-+ * {@link UnsupportedOperationException}.
-+ */
-+
-+public abstract class AbstractPriorityQueue<K> implements PriorityQueue<K> {
-+
-+	public void changed() { throw new UnsupportedOperationException(); }
-+
-+	public K last() { throw new UnsupportedOperationException(); }
-+
-+	public boolean isEmpty() { return size() == 0; }
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** An abstract class providing basic methods for implementing the {@link Stack} interface.
-+ *
-+ * <P>This class just defines {@link Stack#top()} as {@link Stack#peek(int) peek(0)}, and
-+ * {@link Stack#peek(int)} as throwing an {@link UnsupportedOperationException}.
-+ *
-+ * Subclasses of this class may choose to implement just {@link Stack#push(Object)},
-+ * {@link Stack#pop()} and {@link Stack#isEmpty()}, or (but this is not
-+ * required) go farther and implement {@link Stack#top()}, or even {@link
-+ * Stack#peek(int)}.
-+ */
-+
-+public abstract class AbstractStack<K> implements Stack<K> {
-+
-+	public K top() {
-+		return peek( 0 );
-+	}
-+
-+	public K peek( int i ) {
-+		throw new UnsupportedOperationException();
-+	}
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Arrays.java b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+import it.unimi.dsi.fastutil.ints.IntComparator;
-+
-+import java.util.ArrayList;
-+import java.util.concurrent.ForkJoinPool;
-+import java.util.concurrent.RecursiveAction;
-+
-+/** A class providing static methods and objects that do useful things with arrays.
-+ *
-+ * <p>In addition to commodity methods, this class contains {@link Swapper}-based implementations
-+ * of {@linkplain #quickSort(int, int, IntComparator, Swapper) quicksort} and of
-+ * a stable, in-place {@linkplain #mergeSort(int, int, IntComparator, Swapper) mergesort}. These
-+ * generic sorting methods can be used to sort any kind of list, but they find their natural
-+ * usage, for instance, in sorting arrays in parallel.
-+ *
-+ * @see Arrays
-+ */
-+
-+public class Arrays {
-+	
-+	private Arrays() {}
-+
-+	/** This is a safe value used by {@link ArrayList} (as of Java 7) to avoid
-+	 *  throwing {@link OutOfMemoryError} on some JVMs. We adopt the same value. */
-+    public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
-+
-+    /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array of given length.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param arrayLength an array length.
-+	 * @param from a start index (inclusive).
-+	 * @param to an end index (inclusive).
-+	 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than <code>arrayLength</code> or negative.
-+	 */
-+	public static void ensureFromTo( final int arrayLength, final int from, final int to ) {
-+		if ( from < 0 ) throw new ArrayIndexOutOfBoundsException( "Start index (" + from + ") is negative" );
-+		if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+		if ( to > arrayLength ) throw new ArrayIndexOutOfBoundsException( "End index (" + to + ") is greater than array length (" + arrayLength + ")" );
-+	}
-+
-+	/** Ensures that a range given by an offset and a length fits an array of given length.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param arrayLength an array length.
-+	 * @param offset a start index for the fragment
-+	 * @param length a length (the number of elements in the fragment).
-+	 * @throws IllegalArgumentException if <code>length</code> is negative.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than <code>arrayLength</code>.
-+	 */
-+	public static void ensureOffsetLength( final int arrayLength, final int offset, final int length ) {
-+		if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+		if ( length < 0 ) throw new IllegalArgumentException( "Length (" + length + ") is negative" );
-+		if ( offset + length > arrayLength ) throw new ArrayIndexOutOfBoundsException( "Last index (" + ( offset + length ) + ") is greater than array length (" + arrayLength + ")" );
-+	}
-+
-+	/**
-+	 * Transforms two consecutive sorted ranges into a single sorted range. The initial ranges are
-+	 * <code>[first..middle)</code> and <code>[middle..last)</code>, and the resulting range is
-+	 * <code>[first..last)</code>. Elements in the first input range will precede equal elements in
-+	 * the second.
-+	 */
-+	private static void inPlaceMerge( final int from, int mid, final int to, final IntComparator comp, final Swapper swapper ) {
-+		if ( from >= mid || mid >= to ) return;
-+		if ( to - from == 2 ) {
-+			if ( comp.compare( mid, from ) < 0 ) swapper.swap( from, mid );
-+			return;
-+		}
-+
-+		int firstCut;
-+		int secondCut;
-+
-+		if ( mid - from > to - mid ) {
-+			firstCut = from + ( mid - from ) / 2;
-+			secondCut = lowerBound( mid, to, firstCut, comp );
-+		}
-+		else {
-+			secondCut = mid + ( to - mid ) / 2;
-+			firstCut = upperBound( from, mid, secondCut, comp );
-+		}
-+
-+		int first2 = firstCut;
-+		int middle2 = mid;
-+		int last2 = secondCut;
-+		if ( middle2 != first2 && middle2 != last2 ) {
-+			int first1 = first2;
-+			int last1 = middle2;
-+			while ( first1 < --last1 )
-+				swapper.swap( first1++, last1 );
-+			first1 = middle2;
-+			last1 = last2;
-+			while ( first1 < --last1 )
-+				swapper.swap( first1++, last1 );
-+			first1 = first2;
-+			last1 = last2;
-+			while ( first1 < --last1 )
-+				swapper.swap( first1++, last1 );
-+		}
-+
-+		mid = firstCut + ( secondCut - mid );
-+		inPlaceMerge( from, firstCut, mid, comp, swapper );
-+		inPlaceMerge( mid, secondCut, to, comp, swapper );
-+	}
-+
-+	/**
-+	 * Performs a binary search on an already-sorted range: finds the first position where an
-+	 * element can be inserted without violating the ordering. Sorting is by a user-supplied
-+	 * comparison function.
-+	 * 
-+	 * @param from the index of the first element (inclusive) to be included in the binary search.
-+	 * @param to the index of the last element (exclusive) to be included in the binary search.
-+	 * @param pos the position of the element to be searched for.
-+	 * @param comp the comparison function.
-+	 * @return the largest index i such that, for every j in the range <code>[first..i)</code>,
-+	 * <code>comp.compare(j, pos)</code> is <code>true</code>.
-+	 */
-+	private static int lowerBound( int from, final int to, final int pos, final IntComparator comp ) {
-+		// if (comp==null) throw new NullPointerException();
-+		int len = to - from;
-+		while ( len > 0 ) {
-+			int half = len / 2;
-+			int middle = from + half;
-+			if ( comp.compare( middle, pos ) < 0 ) {
-+				from = middle + 1;
-+				len -= half + 1;
-+			}
-+			else {
-+				len = half;
-+			}
-+		}
-+		return from;
-+	}
-+
-+
-+	/**
-+	 * Performs a binary search on an already sorted range: finds the last position where an element
-+	 * can be inserted without violating the ordering. Sorting is by a user-supplied comparison
-+	 * function.
-+	 * 
-+	 * @param from the index of the first element (inclusive) to be included in the binary search.
-+	 * @param to the index of the last element (exclusive) to be included in the binary search.
-+	 * @param pos the position of the element to be searched for.
-+	 * @param comp the comparison function.
-+	 * @return The largest index i such that, for every j in the range <code>[first..i)</code>,
-+	 * <code>comp.compare(pos, j)</code> is <code>false</code>.
-+	 */
-+	private static int upperBound( int from, final int mid, final int pos, final IntComparator comp ) {
-+		// if (comp==null) throw new NullPointerException();
-+		int len = mid - from;
-+		while ( len > 0 ) {
-+			int half = len / 2;
-+			int middle = from + half;
-+			if ( comp.compare( pos, middle ) < 0 ) {
-+				len = half;
-+			}
-+			else {
-+				from = middle + 1;
-+				len -= half + 1;
-+			}
-+		}
-+		return from;
-+	}
-+
-+	/**
-+	 * Returns the index of the median of the three indexed chars.
-+	 */
-+	private static int med3( final int a, final int b, final int c, final IntComparator comp ) {
-+		int ab = comp.compare( a, b );
-+		int ac = comp.compare( a, c );
-+		int bc = comp.compare( b, c );
-+		return ( ab < 0 ?
-+				( bc < 0 ? b : ac < 0 ? c : a ) :
-+				( bc > 0 ? b : ac > 0 ? c : a ) );
-+	}
-+
-+	 private static final int MERGESORT_NO_REC = 16;
-+
-+	 /** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. The sorting algorithm is an in-place mergesort that is significantly slower than a 
-+	 * standard mergesort, as its running time is <i>O</i>(<var>n</var>&nbsp;(log&nbsp;<var>n</var>)<sup>2</sup>), but it does not allocate additional memory; as a result, it can be
-+	 * used as a generic sorting algorithm.
-+	 * 
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param c the comparator to determine the order of the generic data (arguments are positions).
-+	 * @param swapper an object that knows how to swap the elements at any two positions.
-+	 */
-+	public static void mergeSort( final int from, final int to, final IntComparator c, final Swapper swapper ) {
-+		/*
-+		 * We retain the same method signature as quickSort. Given only a comparator and swapper we
-+		 * do not know how to copy and move elements from/to temporary arrays. Hence, in contrast to
-+		 * the JDK mergesorts this is an "in-place" mergesort, i.e. does not allocate any temporary
-+		 * arrays. A non-inplace mergesort would perhaps be faster in most cases, but would require
-+		 * non-intuitive delegate objects...
-+		 */
-+		final int length = to - from;
-+
-+		// Insertion sort on smallest arrays
-+		if ( length < MERGESORT_NO_REC ) {
-+			for ( int i = from; i < to; i++ ) {
-+				for ( int j = i; j > from && ( c.compare( j - 1, j ) > 0 ); j-- ) {
-+					swapper.swap( j, j - 1 );
-+				}
-+			}
-+			return;
-+		}
-+
-+		// Recursively sort halves
-+		int mid = ( from + to ) >>> 1;
-+		mergeSort( from, mid, c, swapper );
-+		mergeSort( mid, to, c, swapper );
-+
-+		// If list is already sorted, nothing left to do. This is an
-+		// optimization that results in faster sorts for nearly ordered lists.
-+		if ( c.compare( mid - 1, mid ) <= 0 ) return;
-+
-+		// Merge sorted halves
-+		inPlaceMerge( from, mid, to, c, swapper );
-+	}
-+
-+	/** Swaps two sequences of elements using a provided swapper.
-+	 *
-+	 * @param swapper the swapper.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 * @param n the number of elements to exchange starting at {@code a} and {@code b}.
-+	 */
-+	protected static void swap( final Swapper swapper, int a, int b, final int n ) {
-+		for ( int i = 0; i < n; i++, a++, b++ ) swapper.swap( a, b );
-+	}
-+
-+	private static final int QUICKSORT_NO_REC = 16;
-+	private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
-+	private static final int QUICKSORT_MEDIAN_OF_9 = 128;
-+
-+	protected static class ForkJoinGenericQuickSort extends RecursiveAction {
-+		private static final long serialVersionUID = 1L;
-+		private final int from;
-+		private final int to;
-+		private final IntComparator comp;
-+		private final Swapper swapper;
-+
-+		public ForkJoinGenericQuickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
-+			this.from = from;
-+			this.to = to;
-+			this.comp = comp;
-+			this.swapper = swapper;
-+		}
-+
-+		@Override
-+		protected void compute() {
-+			final int len = to - from;
-+			if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+				quickSort( from, to, comp, swapper );
-+				return;
-+			}
-+			// Choose a partition element, v
-+			int m = from + len / 2;
-+			int l = from;
-+			int n = to - 1;
-+			int s = len / 8;
-+			l = med3( l, l + s, l + 2 * s, comp );
-+			m = med3( m - s, m, m + s, comp );
-+			n = med3( n - 2 * s, n - s, n, comp );
-+			m = med3( l, m, n, comp );
-+			// Establish Invariant: v* (<v)* (>v)* v*
-+			int a = from, b = a, c = to - 1, d = c;
-+			while ( true ) {
-+				int comparison;
-+				while ( b <= c && ( ( comparison = comp.compare( b, m ) ) <= 0 ) ) {
-+					if ( comparison == 0 ) {
-+						// Fix reference to pivot if necessary
-+						if ( a == m ) m = b;
-+						else if ( b == m ) m = a;
-+						swapper.swap( a++, b );
-+					}
-+					b++;
-+				}
-+				while ( c >= b && ( ( comparison = comp.compare( c, m ) ) >= 0 ) ) {
-+					if ( comparison == 0 ) {
-+						// Fix reference to pivot if necessary
-+						if ( c == m ) m = d;
-+						else if ( d == m ) m = c;
-+						swapper.swap( c, d-- );
-+					}
-+					c--;
-+				}
-+				if ( b > c ) break;
-+				// Fix reference to pivot if necessary
-+				if ( b == m ) m = d;
-+				else if ( c == m ) m = c;
-+				swapper.swap( b++, c-- );
-+			}
-+
-+			// Swap partition elements back to middle
-+			s = Math.min( a - from, b - a );
-+			swap( swapper, from, b - s, s );
-+			s = Math.min( d - c, to - d - 1 );
-+			swap( swapper, b, to - s, s );
-+
-+			// Recursively sort non-partition-elements
-+			int t;
-+			s = b - a;
-+			t = d - c;
-+			if ( s > 1 && t > 1 ) invokeAll( new ForkJoinGenericQuickSort( from, from + s, comp, swapper ), new ForkJoinGenericQuickSort( to - t, to, comp, swapper ) );
-+			else if ( s > 1 ) invokeAll( new ForkJoinGenericQuickSort( from, from + s, comp, swapper ) );
-+			else invokeAll( new ForkJoinGenericQuickSort( to - t, to, comp, swapper ) );
-+		}
-+	}
-+
-+	/** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the order of the generic data.
-+	 * @param swapper an object that knows how to swap the elements at any two positions.
-+	 * 
-+	 */
-+	public static void parallelQuickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
-+		final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+		pool.invoke( new ForkJoinGenericQuickSort( from, to, comp, swapper ) );
-+		pool.shutdown();
-+	}
-+
-+
-+	/** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
-+	 * comparator using parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the order of the generic data.
-+	 * @param swapper an object that knows how to swap the elements at any two positions.
-+	 * 
-+	 */
-+	public static void quickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
-+		final int len = to - from;
-+		// Insertion sort on smallest arrays
-+		if ( len < QUICKSORT_NO_REC ) {
-+			for ( int i = from; i < to; i++ )
-+				for ( int j = i; j > from && ( comp.compare( j - 1, j ) > 0 ); j-- ) {
-+					swapper.swap( j, j - 1 );
-+				}
-+			return;
-+		}
-+
-+		// Choose a partition element, v
-+		int m = from + len / 2; // Small arrays, middle element
-+		int l = from;
-+		int n = to - 1;
-+		if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+			int s = len / 8;
-+			l = med3( l, l + s, l + 2 * s, comp );
-+			m = med3( m - s, m, m + s, comp );
-+			n = med3( n - 2 * s, n - s, n, comp );
-+		}
-+		m = med3( l, m, n, comp ); // Mid-size, med of 3
-+		// int v = x[m];
-+
-+		int a = from;
-+		int b = a;
-+		int c = to - 1;
-+		// Establish Invariant: v* (<v)* (>v)* v*
-+		int d = c;
-+		while ( true ) {
-+			int comparison;
-+			while ( b <= c && ( ( comparison = comp.compare( b, m ) ) <= 0 ) ) {
-+				if ( comparison == 0 ) {
-+					// Fix reference to pivot if necessary
-+					if ( a == m ) m = b;
-+					else if ( b == m ) m = a;
-+					swapper.swap( a++, b );
-+				}
-+				b++;
-+			}
-+			while ( c >= b && ( ( comparison = comp.compare( c, m ) ) >= 0 ) ) {
-+				if ( comparison == 0 ) {
-+					// Fix reference to pivot if necessary
-+					if ( c == m ) m = d;
-+					else if ( d == m ) m = c;
-+					swapper.swap( c, d-- );
-+				}
-+				c--;
-+			}
-+			if ( b > c ) break;
-+			// Fix reference to pivot if necessary
-+			if ( b == m ) m = d;
-+			else if ( c == m ) m = c;
-+			swapper.swap( b++, c-- );
-+		}
-+
-+		// Swap partition elements back to middle
-+		int s;
-+		s = Math.min( a - from, b - a );
-+		swap( swapper, from, b - s, s );
-+		s = Math.min( d - c, to - d - 1 );
-+		swap( swapper, b, to - s, s );
-+
-+		// Recursively sort non-partition-elements
-+		if ( ( s = b - a ) > 1 ) quickSort( from, from + s, comp, swapper );
-+		if ( ( s = d - c ) > 1 ) quickSort( to - s, to, comp, swapper );
-+	}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+
-+/** A bidirectional {@link Iterator}.
-+ *
-+ * <P>This kind of iterator is essentially a {@link ListIterator} that
-+ * does not support {@link ListIterator#previousIndex()} and {@link
-+ * ListIterator#nextIndex()}. It is useful for those maps that can easily
-+ * provide bidirectional iteration, but provide no index.
-+ *
-+ * <P>Note that iterators returned by <code>fastutil</code> classes are more
-+ * specific, and support skipping. This class serves the purpose of organising
-+ * in a cleaner way the relationships between various iterators.
-+ *
-+ * @see Iterator
-+ * @see ListIterator
-+ */
-+
-+public interface BidirectionalIterator<K> extends Iterator<K> {
-+
-+	/** Returns the previous element from the collection.
-+	 *
-+	 * @return the previous element from the collection.
-+	 * @see java.util.ListIterator#previous()
-+	 */
-+
-+	K previous();
-+
-+	/** Returns whether there is a previous element.
-+	 *
-+	 * @return whether there is a previous element.
-+	 * @see java.util.ListIterator#hasPrevious()
-+	 */
-+
-+	boolean hasPrevious();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2010-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** An object that can swap elements whose positions is specified by longs. 
-+ * 
-+ * @see BigArrays#quickSort(long, long, it.unimi.dsi.fastutil.longs.LongComparator, BigSwapper) 
-+ */
-+
-+public interface BigSwapper {
-+	/** Swaps the data at the given positions.
-+	 * 
-+	 * @param a the first position to swap.
-+	 * @param b the second position to swap.
-+	 */
-+	void swap( long a, long b );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Function.java b/src/main/java/it/unimi/dsi/fastutil/Function.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Function.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** A function mapping keys into values.
-+ * 
-+ * <p>Instances of this class represent functions: the main difference with {@link java.util.Map}
-+ * is that functions do not in principle allow enumeration of their domain or range. The need for
-+ * this interface lies in the existence of several highly optimized implementations of 
-+ * functions (e.g., minimal perfect hashes) which do not actually store their domain or range explicitly.
-+ * In case the domain is known, {@link #containsKey(Object)} can be used to perform membership queries. 
-+ *
-+ * <p>The choice of naming all methods exactly as in {@link java.util.Map} makes it possible
-+ * for all type-specific maps to extend type-specific functions (e.g., {@link it.unimi.dsi.fastutil.ints.Int2IntMap}
-+ * extends {@link it.unimi.dsi.fastutil.ints.Int2IntFunction}). However, {@link #size()} is allowed to return -1 to denote
-+ * that the number of keys is not available (e.g., in the case of a string hash function).
-+ * 
-+ * <p>Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction} that
-+ * can also set its default return value.
-+ * 
-+ * <p><strong>Warning</strong>: Equality of functions is <em>not specified</em>
-+ * by contract, and it will usually be <em>by reference</em>, as there is no way to enumerate the keys
-+ * and establish whether two functions represent the same mathematical entity.
-+ *
-+ * @see java.util.Map
-+ */
-+
-+public interface Function<K,V> {
-+
-+	/** Associates the specified value with the specified key in this function (optional operation).
-+	 *
-+	 * @param key the key.
-+	 * @param value the value.
-+	 * @return the old value, or <code>null</code> if no value was present for the given key.
-+	 * @see java.util.Map#put(Object,Object)
-+	 */
-+
-+	V put( K key, V value );
-+
-+	/** Returns the value associated by this function to the specified key. 
-+	 *
-+	 * @param key the key.
-+	 * @return the corresponding value, or <code>null</code> if no value was present for the given key.
-+	 * @see java.util.Map#get(Object)
-+	 */
-+
-+	V get( Object key );
-+
-+	/** Returns true if this function contains a mapping for the specified key. 
-+	 *
-+	 * <p>Note that for some kind of functions (e.g., hashes) this method
-+	 * will always return true.
-+	 *
-+	 * @param key the key.
-+	 * @return true if this function associates a value to <code>key</code>.
-+	 * @see java.util.Map#containsKey(Object)
-+	 */
-+
-+	 boolean containsKey( Object key );
-+
-+	/** Removes this key and the associated value from this function if it is present (optional operation).
-+	 *  
-+	 * @param key the key.
-+	 * @return the old value, or <code>null</code> if no value was present for the given key.
-+	 * @see java.util.Map#remove(Object)
-+	 */
-+	
-+	V remove( Object key );
-+
-+	/** Returns the intended number of keys in this function, or -1 if no such number exists.
-+	 * 
-+	 * <p>Most function implementations will have some knowledge of the intended number of keys
-+	 * in their domain. In some cases, however, this might not be possible.
-+	 * 
-+	 *  @return the intended number of keys in this function, or -1 if that number is not available.
-+	 */
-+    int size();
-+
-+	/** Removes all associations from this function (optional operation).
-+	 *  
-+	 * @see java.util.Map#clear()
-+	 */
-+	
-+	void clear();
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Hash.java b/src/main/java/it/unimi/dsi/fastutil/Hash.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Hash.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** Basic data for all hash-based classes.
-+ *
-+ * <h2>Historical note</h2>
-+ * 
-+ * <p><strong>Warning:</strong> the following comments are here for historical reasons,
-+ * and apply just to the <em>double hash</em> classes that can be optionally generated.
-+ * The standard <code>fastutil</code> distribution since 6.1.0 uses linear-probing hash
-+ * tables, and tables are always sized as powers of two. 
-+ *
-+ * <p>The classes in <code>fastutil</code> are built around open-addressing hashing
-+ * implemented <em>via</em> double hashing. Following Knuth's suggestions in the third volume of <em>The Art of Computer
-+ * Programming</em>, we use for the table size a prime <var>p</var> such that
-+ * <var>p</var>-2 is also prime. In this way hashing is implemented with modulo <var>p</var>,
-+ * and secondary hashing with modulo <var>p</var>-2.
-+ *
-+ * <p>Entries in a table can be in three states: {@link #FREE}, {@link #OCCUPIED} or {@link #REMOVED}.
-+ * The naive handling of removed entries requires that you search for a free entry as if they were occupied. However,
-+ * <code>fastutil</code> implements two useful optimizations, based on the following invariant:
-+ * <blockquote>
-+ * Let <var>i</var><sub>0</sub>, <var>i</var><sub>1</sub>, &hellip;, <var>i</var><sub><var>p</var>-1</sub> be
-+ * the permutation of the table indices induced by the key <var>k</var>, that is, <var>i</var><sub>0</sub> is the hash
-+ * of <var>k</var> and the following indices are obtained by adding (modulo <var>p</var>) the secondary hash plus one.
-+ * If there is a {@link #OCCUPIED} entry with key <var>k</var>, its index in the sequence above comes <em>before</em>
-+ * the indices of any {@link #REMOVED} entries with key <var>k</var>.
-+ * </blockquote>
-+ * 
-+ * <p>When we search for the key <var>k</var> we scan the entries in the
-+ * sequence <var>i</var><sub>0</sub>, <var>i</var><sub>1</sub>, &hellip;,
-+ * <var>i</var><sub><var>p</var>-1</sub> and stop when <var>k</var> is found,
-+ * when we finished the sequence or when we find a {@link #FREE} entry. Note
-+ * that the correctness of this procedure it is not completely trivial. Indeed,
-+ * when we stop at a {@link #REMOVED} entry with key <var>k</var> we must rely
-+ * on the invariant to be sure that no {@link #OCCUPIED} entry with the same
-+ * key can appear later. If we insert and remove frequently the same entries,
-+ * this optimization can be very effective (note, however, that when using
-+ * objects as keys or values deleted entries are set to a special fixed value to
-+ * optimize garbage collection).
-+ *
-+ * <p>Moreover, during the probe we keep the index of the first {@link #REMOVED} entry we meet. 
-+ * If we actually have to insert a new element, we use that 
-+ * entry if we can, thus avoiding to pollute another {@link #FREE} entry. Since this position comes
-+ * <i>a fortiori</i> before any {@link #REMOVED} entries with the same key, we are also keeping the invariant true.
-+ */
-+
-+public interface Hash {
-+
-+	/** The initial default size of a hash table. */
-+	final public int DEFAULT_INITIAL_SIZE = 16;
-+	/** The default load factor of a hash table. */
-+	final public float DEFAULT_LOAD_FACTOR = .75f;
-+	/** The load factor for a (usually small) table that is meant to be particularly fast. */
-+	final public float FAST_LOAD_FACTOR = .5f;
-+	/** The load factor for a (usually very small) table that is meant to be extremely fast. */
-+	final public float VERY_FAST_LOAD_FACTOR = .25f;
-+
-+	/** A generic hash strategy.
-+	 *
-+	 * <P>Custom hash structures (e.g., {@link
-+	 * it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet}) allow to hash objects
-+	 * using arbitrary functions, a typical example being that of {@linkplain
-+	 * it.unimi.dsi.fastutil.ints.IntArrays#HASH_STRATEGY arrays}. Of course,
-+	 * one has to compare objects for equality consistently with the chosen
-+	 * function. A <em>hash strategy</em>, thus, specifies an {@linkplain
-+	 * #equals(Object,Object) equality method} and a {@linkplain
-+	 * #hashCode(Object) hash function}, with the obvious property that
-+	 * equal objects must have the same hash code.
-+	 *
-+	 * <P>Note that the {@link #equals(Object,Object) equals()} method of a strategy must 
-+	 * be able to handle <code>null</code>, too.
-+	 */
-+
-+	public interface Strategy<K> {
-+
-+		/** Returns the hash code of the specified object with respect to this hash strategy.
-+		 *
-+		 * @param o an object (or <code>null</code>).
-+		 * @return the hash code of the given object with respect to this hash strategy.
-+		 */
-+
-+		public int hashCode( K o );
-+
-+		/** Returns true if the given objects are equal with respect to this hash strategy.
-+		 *
-+		 * @param a an object (or <code>null</code>).
-+		 * @param b another object (or <code>null</code>).
-+		 * @return true if the two specified objects are equal with respect to this hash strategy.
-+		 */
-+		public boolean equals( K a, K b );
-+	}
-+
-+	/** The default growth factor of a hash table. */
-+	final public int DEFAULT_GROWTH_FACTOR = 16;
-+	/** The state of a free hash table entry. */
-+	final public byte FREE = 0;
-+	/** The state of a occupied hash table entry. */
-+	final public byte OCCUPIED = -1;
-+	/** The state of a hash table entry freed by a deletion. */
-+	final public byte REMOVED = 1;
-+	 
-+	/** A list of primes to be used as table sizes. The <var>i</var>-th element is 
-+	 *  the largest prime <var>p</var> smaller than 2<sup>(<var>i</var>+28)/16</sup> 
-+	 * and such that <var>p</var>-2 is also prime (or 1, for the first few entries). */
-+
-+	final public int PRIMES[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 7, 7, 7,
-+								  7, 7, 7, 7, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13, 19, 19, 19, 19, 19,
-+								  19, 19, 19, 19, 19, 19, 19, 31, 31, 31, 31, 31, 31, 31, 43, 43, 43, 43, 43,
-+								  43, 43, 43, 61, 61, 61, 61, 61, 73, 73, 73, 73, 73, 73, 73, 103, 103, 109,
-+								  109, 109, 109, 109, 139, 139, 151, 151, 151, 151, 181, 181, 193, 199, 199,
-+								  199, 229, 241, 241, 241, 271, 283, 283, 313, 313, 313, 349, 349, 349, 349,
-+								  421, 433, 463, 463, 463, 523, 523, 571, 601, 619, 661, 661, 661, 661, 661,
-+								  823, 859, 883, 883, 883, 1021, 1063, 1093, 1153, 1153, 1231, 1321, 1321,
-+								  1429, 1489, 1489, 1621, 1699, 1789, 1873, 1951, 2029, 2131, 2143, 2311,
-+								  2383, 2383, 2593, 2731, 2803, 3001, 3121, 3259, 3391, 3583, 3673, 3919,
-+								  4093, 4273, 4423, 4651, 4801, 5023, 5281, 5521, 5743, 5881, 6301, 6571,
-+								  6871, 7129, 7489, 7759, 8089, 8539, 8863, 9283, 9721, 10141, 10531, 11071,
-+								  11551, 12073, 12613, 13009, 13759, 14323, 14869, 15649, 16363, 17029,
-+								  17839, 18541, 19471, 20233, 21193, 22159, 23059, 24181, 25171, 26263,
-+								  27541, 28753, 30013, 31321, 32719, 34213, 35731, 37309, 38923, 40639,
-+								  42463, 44281, 46309, 48313, 50461, 52711, 55051, 57529, 60091, 62299,
-+								  65521, 68281, 71413, 74611, 77713, 81373, 84979, 88663, 92671, 96739,
-+								  100801, 105529, 109849, 115021, 120079, 125509, 131011, 136861, 142873,
-+								  149251, 155863, 162751, 169891, 177433, 185071, 193381, 202129, 211063,
-+								  220021, 229981, 240349, 250969, 262111, 273643, 285841, 298411, 311713,
-+								  325543, 339841, 355009, 370663, 386989, 404269, 422113, 440809, 460081,
-+								  480463, 501829, 524221, 547399, 571603, 596929, 623353, 651019, 679909,
-+								  709741, 741343, 774133, 808441, 844201, 881539, 920743, 961531, 1004119,
-+								  1048573, 1094923, 1143283, 1193911, 1246963, 1302181, 1359733, 1420039,
-+								  1482853, 1548541, 1616899, 1688413, 1763431, 1841293, 1922773, 2008081,
-+								  2097133, 2189989, 2286883, 2388163, 2493853, 2604013, 2719669, 2840041,
-+								  2965603, 3097123, 3234241, 3377191, 3526933, 3682363, 3845983, 4016041,
-+								  4193803, 4379719, 4573873, 4776223, 4987891, 5208523, 5439223, 5680153,
-+								  5931313, 6194191, 6468463, 6754879, 7053331, 7366069, 7692343, 8032639,
-+								  8388451, 8759953, 9147661, 9552733, 9975193, 10417291, 10878619, 11360203,
-+								  11863153, 12387841, 12936529, 13509343, 14107801, 14732413, 15384673,
-+								  16065559, 16777141, 17519893, 18295633, 19105483, 19951231, 20834689,
-+								  21757291, 22720591, 23726449, 24776953, 25873963, 27018853, 28215619,
-+								  29464579, 30769093, 32131711, 33554011, 35039911, 36591211, 38211163,
-+								  39903121, 41669479, 43514521, 45441199, 47452879, 49553941, 51747991,
-+								  54039079, 56431513, 58930021, 61539091, 64263571, 67108669, 70079959,
-+								  73182409, 76422793, 79806229, 83339383, 87029053, 90881083, 94906249,
-+								  99108043, 103495879, 108077731, 112863013, 117860053, 123078019, 128526943,
-+								  134217439, 140159911, 146365159, 152845393, 159612601, 166679173,
-+								  174058849, 181765093, 189812341, 198216103, 206991601, 216156043,
-+								  225726379, 235720159, 246156271, 257054491, 268435009, 280319203,
-+								  292730833, 305691181, 319225021, 333358513, 348117151, 363529759,
-+								  379624279, 396432481, 413983771, 432312511, 451452613, 471440161,
-+								  492312523, 514109251, 536870839, 560640001, 585461743, 611382451,
-+								  638450569, 666717199, 696235363, 727060069, 759249643, 792864871,
-+								  827967631, 864625033, 902905501, 942880663, 984625531, 1028218189,
-+								  1073741719, 1121280091, 1170923713, 1222764841, 1276901371, 1333434301,
-+								  1392470281, 1454120779, 1518500173, 1585729993, 1655935399, 1729249999,
-+								  1805811253, 1885761133, 1969251079, 2056437379, 2147482951 };
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/HashCommon.java b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** Common code for all hash-based classes. */
-+
-+public class HashCommon {
-+
-+	protected HashCommon() {};
-+
-+	/** This reference is used to fill keys and values of removed entries (if
-+		they are objects). <code>null</code> cannot be used as it would confuse the
-+		search algorithm in the presence of an actual <code>null</code> key. */ 
-+	public static final Object REMOVED = new Object();
-+
-+    /** 2<sup>32</sup> &middot; &phi;, &phi; = (&#x221A;5 &minus; 1)/2. */
-+    private static final int INT_PHI = 0x9E3779B9;
-+    /** The reciprocal of {@link #INT_PHI} modulo 2<sup>32</sup>. */
-+    private static final int INV_INT_PHI = 0x144cbc89;
-+    /** 2<sup>64</sup> &middot; &phi;, &phi; = (&#x221A;5 &minus; 1)/2. */
-+    private static final long LONG_PHI = 0x9E3779B97F4A7C15L;
-+    /** The reciprocal of {@link #LONG_PHI} modulo 2<sup>64</sup>. */
-+    private static final long INV_LONG_PHI = 0xf1de83e19937733dL;
-+    
-+	/** Avalanches the bits of an integer by applying the finalisation step of MurmurHash3.
-+	 * 
-+	 * <p>This method implements the finalisation step of Austin Appleby's <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
-+	 * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
-+	 * 
-+	 * @param x an integer.
-+	 * @return a hash value with good avalanching properties.
-+	 */	
-+	public final static int murmurHash3( int x ) {
-+		x ^= x >>> 16;
-+		x *= 0x85ebca6b;
-+		x ^= x >>> 13;
-+		x *= 0xc2b2ae35;
-+		x ^= x >>> 16;
-+		return x;
-+	}
-+
-+
-+	/** Avalanches the bits of a long integer by applying the finalisation step of MurmurHash3.
-+	 * 
-+	 * <p>This method implements the finalisation step of Austin Appleby's <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
-+	 * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
-+	 * 
-+	 * @param x a long integer.
-+	 * @return a hash value with good avalanching properties.
-+	 */	
-+	public final static long murmurHash3( long x ) {
-+		x ^= x >>> 33;
-+		x *= 0xff51afd7ed558ccdL;
-+		x ^= x >>> 33;
-+		x *= 0xc4ceb9fe1a85ec53L;
-+		x ^= x >>> 33;
-+		return x;
-+	}
-+
-+	/** Quickly mixes the bits of an integer.
-+	 * 
-+	 * <p>This method mixes the bits of the argument by multiplying by the golden ratio and 
-+	 * xorshifting the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
-+	 * it has slightly worse behaviour than {@link #murmurHash3(int)} (in open-addressing hash tables the average number of probes
-+	 * is slightly larger), but it's much faster.
-+	 * 
-+	 * @param x an integer.
-+	 * @return a hash value obtained by mixing the bits of {@code x}.
-+	 * @see #invMix(int)
-+	 */	
-+	public final static int mix( final int x ) {
-+		final int h = x * INT_PHI;
-+		return h ^ (h >>> 16);
-+	}
-+
-+	/** The inverse of {@link #mix(int)}. This method is mainly useful to create unit tests.
-+	 * 
-+	 * @param x an integer.
-+	 * @return a value that passed through {@link #mix(int)} would give {@code x}.
-+	 */	
-+	public final static int invMix( final int x ) {
-+		return ( x ^ x >>> 16 ) * INV_INT_PHI; 
-+	}
-+
-+	/** Quickly mixes the bits of a long integer.
-+	 * 
-+	 * <p>This method mixes the bits of the argument by multiplying by the golden ratio and 
-+	 * xorshifting twice the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
-+	 * it has slightly worse behaviour than {@link #murmurHash3(long)} (in open-addressing hash tables the average number of probes
-+	 * is slightly larger), but it's much faster. 
-+	 * 
-+	 * @param x a long integer.
-+	 * @return a hash value obtained by mixing the bits of {@code x}.
-+	 */	
-+	public final static long mix( final long x ) {
-+		long h = x * LONG_PHI;
-+		h ^= h >>> 32;
-+		return h ^ (h >>> 16);
-+	}
-+
-+	/** The inverse of {@link #mix(long)}. This method is mainly useful to create unit tests.
-+	 * 
-+	 * @param x a long integer.
-+	 * @return a value that passed through {@link #mix(long)} would give {@code x}.
-+	 */	
-+	public final static long invMix( long x ) {
-+		x ^= x >>> 32;
-+		x ^= x >>> 16;
-+		return ( x ^ x >>> 32 ) * INV_LONG_PHI; 
-+	}
-+
-+
-+	/** Returns the hash code that would be returned by {@link Float#hashCode()}.
-+	 *
-+	 * @param f a float.
-+	 * @return the same code as {@link Float#hashCode() new Float(f).hashCode()}.
-+	 */
-+
-+	final public static int float2int( final float f ) {
-+		return Float.floatToRawIntBits( f );
-+	}
-+
-+	/** Returns the hash code that would be returned by {@link Double#hashCode()}.
-+	 *
-+	 * @param d a double.
-+	 * @return the same code as {@link Double#hashCode() new Double(f).hashCode()}.
-+	 */
-+
-+	final public static int double2int( final double d ) {
-+		final long l = Double.doubleToRawLongBits( d );
-+		return (int)( l ^ ( l >>> 32 ) );
-+	}
-+
-+	/** Returns the hash code that would be returned by {@link Long#hashCode()}.
-+	 * 
-+	 * @param l a long.
-+	 * @return the same code as {@link Long#hashCode() new Long(f).hashCode()}.
-+	 */
-+	final public static int long2int( final long l ) {
-+		return (int)( l ^ ( l >>> 32 ) );
-+	}
-+	
-+	/** Return the least power of two greater than or equal to the specified value.
-+	 * 
-+	 * <p>Note that this function will return 1 when the argument is 0.
-+	 * 
-+	 * @param x an integer smaller than or equal to 2<sup>30</sup>.
-+	 * @return the least power of two greater than or equal to the specified value.
-+	 */
-+	public static int nextPowerOfTwo( int x ) {
-+		if ( x == 0 ) return 1;
-+		x--;
-+		x |= x >> 1;
-+		x |= x >> 2;
-+		x |= x >> 4;
-+		x |= x >> 8;
-+		return ( x | x >> 16 ) + 1;
-+	}
-+
-+	/** Return the least power of two greater than or equal to the specified value.
-+	 * 
-+	 * <p>Note that this function will return 1 when the argument is 0.
-+	 * 
-+	 * @param x a long integer smaller than or equal to 2<sup>62</sup>.
-+	 * @return the least power of two greater than or equal to the specified value.
-+	 */
-+	public static long nextPowerOfTwo( long x ) {
-+		if ( x == 0 ) return 1;
-+		x--;
-+		x |= x >> 1;
-+		x |= x >> 2;
-+		x |= x >> 4;
-+		x |= x >> 8;
-+		x |= x >> 16;
-+		return ( x | x >> 32 ) + 1;
-+	}
-+
-+
-+	/** Returns the maximum number of entries that can be filled before rehashing. 
-+	 *
-+	 * @param n the size of the backing array.
-+	 * @param f the load factor.
-+	 * @return the maximum number of entries before rehashing. 
-+	 */
-+	public static int maxFill( final int n, final float f ) {
-+		/* We must guarantee that there is always at least 
-+		 * one free entry (even with pathological load factors). */
-+		return Math.min( (int)Math.ceil( n * f ), n - 1 );
-+	}
-+
-+	/** Returns the maximum number of entries that can be filled before rehashing. 
-+	 * 
-+	 * @param n the size of the backing array.
-+	 * @param f the load factor.
-+	 * @return the maximum number of entries before rehashing. 
-+	 */
-+	public static long maxFill( final long n, final float f ) {
-+		/* We must guarantee that there is always at least 
-+		 * one free entry (even with pathological load factors). */
-+		return Math.min( (long)Math.ceil( n * f ), n - 1 );
-+	}
-+
-+	/** Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to <code>Math.ceil( expected / f )</code>. 
-+	 * 
-+	 * @param expected the expected number of elements in a hash table.
-+	 * @param f the load factor.
-+	 * @return the minimum possible size for a backing array.
-+	 * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
-+	 */
-+	public static int arraySize( final int expected, final float f ) {
-+		final long s = Math.max( 2, nextPowerOfTwo( (long)Math.ceil( expected / f ) ) );
-+		if ( s > (1 << 30) ) throw new IllegalArgumentException( "Too large (" + expected + " expected elements with load factor " + f + ")" );
-+		return (int)s;
-+	}
-+
-+	/** Returns the least power of two larger than or equal to <code>Math.ceil( expected / f )</code>. 
-+	 * 
-+	 * @param expected the expected number of elements in a hash table.
-+	 * @param f the load factor.
-+	 * @return the minimum possible size for a backing big array.
-+	 */
-+	public static long bigArraySize( final long expected, final float f ) {
-+		return nextPowerOfTwo( (long)Math.ceil( expected / f ) );
-+	}
-+}
-\ No newline at end of file
-diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+
-+/** An indirect double priority queue.
-+ *
-+ * <P>An indirect double priority queue uses two distinct comparators (called <em>primary</em>
-+ * and <em>secondary</em>) to keep its elements ordered. It makes it possible to access the
-+ * first element w.r.t. the secondary comparatory using {@link #secondaryFirst()} (and, optionally,
-+ * the last element using  {@link #secondaryLast()}). The remaining methods
-+ * work like those of an {@linkplain it.unimi.dsi.fastutil.IndirectPriorityQueue indirect priority queue} based on the
-+ * primary comparator.
-+ */
-+
-+public interface IndirectDoublePriorityQueue<K> extends IndirectPriorityQueue<K> {
-+
-+	/** Returns the secondary comparator of this queue.
-+	 *
-+	 * @return the secondary comparator of this queue.
-+	 * @see #secondaryFirst()
-+	 */
-+	public Comparator<? super K> secondaryComparator();
-+
-+	/** Returns the first element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator}.
-+	 *
-+	 * @return the first element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
-+	 */
-+	public int secondaryFirst();
-+
-+	/** Returns the last element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator} (optional operation).
-+	 *
-+	 * @return the last element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
-+	 */
-+	public int secondaryLast();
-+
-+    /** Retrieves the secondary front of the queue in a given array (optional operation).
-+    *
-+    * @param a an array large enough to hold the secondary front (e.g., at least long as the reference array).
-+    * @return the number of elements actually written (starting from the first position of <code>a</code>).
-+    * @see IndirectPriorityQueue#front(int[])
-+    */
-+
-+	public int secondaryFront( final int[] a );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+import java.util.NoSuchElementException;
-+
-+/** A class providing static methods and objects that do useful things with indirect priority queues.
-+ *
-+ * @see IndirectDoublePriorityQueue
-+ */
-+
-+public class IndirectDoublePriorityQueues {
-+
-+	private IndirectDoublePriorityQueues() {}
-+
-+	/** An immutable class representing the empty indirect double priority queue.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * {@link IndirectDoublePriorityQueue}.
-+	 */
-+
-+	public static class EmptyIndirectDoublePriorityQueue extends IndirectPriorityQueues.EmptyIndirectPriorityQueue {
-+
-+		protected EmptyIndirectDoublePriorityQueue() {}
-+
-+		public int secondaryFirst() { throw new NoSuchElementException(); }
-+		public int secondaryLast() { throw new NoSuchElementException(); }
-+		public Comparator<?> secondaryComparator() { return null; }
-+		
-+	}
-+
-+	/** An empty indirect double priority queue (immutable).
-+	 */
-+
-+	public final static EmptyIndirectDoublePriorityQueue EMPTY_QUEUE = new EmptyIndirectDoublePriorityQueue();
-+
-+
-+	/** A synchronized wrapper class for indirect double priority queues. */
-+
-+	public static class SynchronizedIndirectDoublePriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
-+		
-+		public static final long serialVersionUID = -7046029254386353129L;
-+
-+		final protected IndirectDoublePriorityQueue<K> q;
-+		final protected Object sync;
-+
-+		protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q, final Object sync ) {
-+			this.q = q;
-+			this.sync = sync;
-+		}
-+
-+		protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q ) {
-+			this.q = q;
-+			this.sync = this;
-+		}
-+
-+		public void enqueue( int index ) { synchronized( sync ) { q.enqueue( index ); } }
-+		public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
-+		public int first() { synchronized( sync ) { return q.first(); } }
-+		public int last() { synchronized( sync ) { return q.last(); } }
-+		public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
-+		public int secondaryFirst() { synchronized( sync ) { return q.secondaryFirst(); } }
-+		public int secondaryLast() { synchronized( sync ) { return q.secondaryLast(); } }
-+		public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
-+		public int size() { synchronized( sync ) { return q.size(); } }
-+		public void clear() { synchronized( sync ) { q.clear(); } }
-+		public void changed() { synchronized( sync ) { q.changed(); } }
-+		public void allChanged() { synchronized( sync ) { q.allChanged(); } }
-+		public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
-+		public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
-+		public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
-+		public Comparator<? super K> secondaryComparator() { synchronized( sync ) { return q.secondaryComparator(); } }
-+		public int secondaryFront( int[] a ) { return q.secondaryFront( a ); }
-+		public int front( int[] a ) { return q.front( a ); }
-+	}
-+
-+
-+	/** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue.
-+	 *
-+	 * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
-+	 * @return a synchronized view of the specified indirect double priority queue.
-+	 */
-+	public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q ) {	return new SynchronizedIndirectDoublePriorityQueue<K>( q ); }
-+
-+	/** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue, using an assigned object to synchronize.
-+	 *
-+	 * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
-+	 * @param sync an object that will be used to synchronize the access to the indirect double priority queue.
-+	 * @return a synchronized view of the specified indirect double priority queue.
-+	 */
-+
-+	public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectDoublePriorityQueue<K>( q, sync ); }
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+import java.util.NoSuchElementException;
-+
-+/** An indirect priority queue.
-+ *
-+ * <P>An indirect priority queue provides a way to {@linkplain #enqueue(int)
-+ * enqueue} by index elements taken from a given <em>reference list</em>,
-+ * and to {@linkplain #dequeue() dequeue} them in some specified order.
-+ * Elements that are <em>smaller</em> in the specified order are
-+ * dequeued first. It
-+ * is also possible to get the {@linkplain #first() index of the first element}, that
-+ * is, the index that would be dequeued next.
-+ *
-+ * <P>Additionally, the queue may provide a method to peek at the index of the
-+ * element that would be dequeued {@linkplain #last() last}.
-+ *
-+ * <P>The reference list should not change during queue operations (or, more
-+ * precisely, the relative order of the elements corresponding to indices in the queue should not
-+ * change). Nonetheless, some implementations may give the caller a way to
-+ * notify the queue that the {@linkplain #changed() first element has changed its 
-+ * relative position in the order}.
-+ *
-+ * <P>Optionally, an indirect priority queue may even provide methods to notify
-+ * {@linkplain #changed(int) the change of <em>any</em> element of the
-+ * reference list}, to check {@linkplain #contains(int) the presence of
-+ * an index in the queue}, and to {@linkplain #remove(int) remove an index from the queue}. 
-+ * It may even allow to notify that {@linkplain #allChanged() all elements have changed}.
-+ *
-+ * <P>It is always possible to enqueue two distinct indices corresponding to
-+ * equal elements of the reference list. However, depending on the
-+ * implementation, it may or may not be possible to enqueue twice the same
-+ * index.
-+ *
-+ * <P>Note that <em>all element manipulation happens via indices</em>.
-+ */
-+
-+public interface IndirectPriorityQueue<K> {
-+
-+	/** Enqueues a new element.
-+	 *
-+	 * @param index the element to enqueue.
-+	 */
-+
-+	void enqueue( int index );
-+
-+	/** Dequeues the {@linkplain #first() first} element from this queue.
-+	 *
-+	 * @return the dequeued element.
-+	 * @throws NoSuchElementException if this queue is empty.
-+	 */
-+
-+	int dequeue();
-+
-+	/** Checks whether this queue is empty.
-+	 *
-+	 * @return true if this queue is empty.
-+	 */
-+
-+	boolean isEmpty();
-+
-+	/** Returns the number of elements in this queue.
-+	 *
-+	 * @return the number of elements in this queue.
-+	 */
-+
-+	int size();
-+
-+	/** Removes all elements from this queue.
-+	 */
-+
-+	void clear();
-+
-+	/** Returns the first element of this queue.
-+	 *
-+	 * @return the first element.
-+	 * @throws NoSuchElementException if this queue is empty.
-+	 */
-+
-+	int first();
-+
-+	/** Returns the last element of this queue, that is, the element the would be dequeued last (optional operation).
-+	 *
-+	 * @return the last element.
-+	 * @throws NoSuchElementException if this queue is empty.
-+	 */
-+
-+	int last();
-+
-+	/** Notifies this queue that the {@linkplain #first() first element} has changed (optional operation).
-+	 *
-+	 */
-+
-+	void changed();
-+
-+    /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
-+	 *
-+	 * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
-+	 */
-+	Comparator <? super K> comparator();
-+
-+	/** Notifies this queue that the specified element has changed (optional operation).
-+	 *
-+	 * <P>Note that the specified element must belong to this queue.
-+	 *
-+	 * @param index the element that has changed.
-+	 * @throws NoSuchElementException if the specified element is not in this queue.
-+	 */
-+
-+	public void changed( int index );
-+
-+	/** Notifies this queue that the all elements have changed (optional operation).
-+	 */
-+
-+	public void allChanged();
-+
-+	/** Checks whether a given index belongs to this queue (optional operation).
-+	 * 
-+	 * @param index an index possibly in the queue.
-+	 * @return true if the specified index belongs to this queue.
-+	 */
-+	public boolean contains( int index );
-+	
-+	/** Removes the specified element from this queue (optional operation).
-+	 *
-+	 * @param index the element to be removed.
-+	 * @return true if the index was in the queue.
-+	 */
-+
-+	public boolean remove( int index );
-+
-+    /** Retrieves the front of this queue in a given array (optional operation).
-+     *
-+     * <p>The <em>front</em> of an indirect queue is the set of indices whose associated elements in the reference array 
-+     * are equal to the element associated to the {@linkplain #first() first index}. These indices can be always obtain by dequeueing, but 
-+     * this method should retrieve efficiently such indices in the given array without modifying the state of this queue.
-+     * 
-+     * @param a an array large enough to hold the front (e.g., at least long as the reference array).
-+     * @return the number of elements actually written (starting from the first position of <code>a</code>).
-+     */
-+
-+	public int front( final int[] a );
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+import java.util.NoSuchElementException;
-+
-+/** A class providing static methods and objects that do useful things with indirect priority queues.
-+ *
-+ * @see IndirectPriorityQueue
-+ */
-+
-+public class IndirectPriorityQueues {
-+
-+	private IndirectPriorityQueues() {}
-+
-+	/** An immutable class representing the empty indirect priority queue.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * {@link IndirectPriorityQueue}.
-+	 */
-+
-+	@SuppressWarnings("rawtypes")
-+	public static class EmptyIndirectPriorityQueue extends AbstractIndirectPriorityQueue {
-+
-+		protected EmptyIndirectPriorityQueue() {}
-+
-+		public void enqueue( final int i ) { throw new UnsupportedOperationException(); }
-+		public int dequeue() { throw new NoSuchElementException(); }
-+		public boolean isEmpty() { return true; }
-+		public int size() { return 0; }
-+		public boolean contains( int index ) { return false; }
-+		public void clear() {}
-+		public int first() { throw new NoSuchElementException(); }
-+		public int last() { throw new NoSuchElementException(); }
-+		public void changed() { throw new NoSuchElementException(); }
-+		public void allChanged() {}
-+		public Comparator<?> comparator() { return null; }
-+		public void changed( final int i ) { throw new IllegalArgumentException( "Index " + i + " is not in the queue" ); }
-+		public boolean remove( final int i ) { return false; }
-+		public int front( int[] a ) { return 0; }
-+		
-+	}
-+
-+	/** An empty indirect priority queue (immutable).
-+	 */
-+
-+	public final static EmptyIndirectPriorityQueue EMPTY_QUEUE = new EmptyIndirectPriorityQueue();
-+
-+
-+	/** A synchronized wrapper class for indirect priority queues. */
-+
-+	public static class SynchronizedIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
-+		
-+		public static final long serialVersionUID = -7046029254386353129L;
-+
-+		final protected IndirectPriorityQueue<K> q;
-+		final protected Object sync;
-+
-+		protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q, final Object sync ) {
-+			this.q = q;
-+			this.sync = sync;
-+		}
-+
-+		protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q ) {
-+			this.q = q;
-+			this.sync = this;
-+		}
-+
-+		public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
-+		public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
-+		public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
-+		public int first() { synchronized( sync ) { return q.first(); } }
-+		public int last() { synchronized( sync ) { return q.last(); } }
-+		public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
-+		public int size() { synchronized( sync ) { return q.size(); } }
-+		public void clear() { synchronized( sync ) { q.clear(); } }
-+		public void changed() { synchronized( sync ) { q.changed(); } }
-+		public void allChanged() { synchronized( sync ) { q.allChanged(); } }
-+		public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
-+		public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
-+		public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
-+		public int front( int[] a ) { return q.front( a ); }
-+	}
-+
-+
-+	/** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue.
-+	 *
-+	 * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
-+	 * @return a synchronized view of the specified indirect priority queue.
-+	 */
-+	public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q ) {	return new SynchronizedIndirectPriorityQueue<K>( q ); }
-+
-+	/** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue, using an assigned object to synchronize.
-+	 *
-+	 * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
-+	 * @param sync an object that will be used to synchronize the access to the indirect priority queue.
-+	 * @return a synchronized view of the specified indirect priority queue.
-+	 */
-+
-+	public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectPriorityQueue<K>( q, sync ); }
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Maps.java b/src/main/java/it/unimi/dsi/fastutil/Maps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Maps.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+/** A class providing static methods and objects that do useful things with maps.
-+ *
-+ * @see java.util.Collections
-+ */
-+
-+public class Maps {
-+
-+	private Maps() {}
-+
-+	/** A standard default return value to be used in maps containing <code>null</code> values.
-+	 * @deprecated Since fastutil 5.0, the introduction of generics
-+	 * makes this object pretty useless.
-+	 */
-+
-+	@Deprecated
-+	public static final Object MISSING = new Object();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+import java.util.NoSuchElementException;
-+
-+/** A priority queue.
-+ *
-+ * <P>A priority queue provides a way to {@linkplain #enqueue(Object) enqueue}
-+ * elements, and to {@linkplain #dequeue() dequeue} them in some specified
-+ * order. Elements that are <em>smaller</em> in the specified order are
-+ * dequeued first.  It is also possible to get the {@linkplain #first() first
-+ * element}, that is, the element that would be dequeued next.
-+ *
-+ * <P>Additionally, the queue may provide a method to peek at 
-+ * element that would be dequeued {@linkplain #last() last}.
-+ *
-+ * <P>The relative order of the elements enqueued should not change during
-+ * queue operations. Nonetheless, some implementations may give the caller a
-+ * way to notify the queue that the {@linkplain #changed() first element has
-+ * changed its relative position in the order}.
-+ */
-+
-+public interface PriorityQueue<K> {
-+
-+	/** Enqueues a new element.
-+	 *
-+	 * @param x the element to enqueue..
-+	 */
-+
-+	void enqueue( K x );
-+
-+	/** Dequeues the {@linkplain #first() first} element from the queue.
-+	 *
-+	 * @return the dequeued element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+
-+	K dequeue();
-+
-+	/** Checks whether the queue is empty.
-+	 *
-+	 * @return true if the queue is empty.
-+	 */
-+
-+	boolean isEmpty();
-+
-+	/** Returns the number of elements in this queue.
-+	 *
-+	 * @return the number of elements in this queue.
-+	 */
-+
-+	int size();
-+
-+	/** Removes all elements from this queue.
-+	 */
-+
-+	void clear();
-+
-+	/** Returns the first element of the queue.
-+	 *
-+	 * @return the first element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+
-+	K first();
-+
-+	/** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
-+	 *
-+	 * @return the last element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+
-+	K last();
-+
-+	/** Notifies the queue that the {@linkplain #first() first} element has changed (optional operation).
-+	 */
-+
-+	void changed();
-+
-+    /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
-+	 *
-+	 * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
-+	 */
-+	Comparator<? super K> comparator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.Comparator;
-+import java.util.NoSuchElementException;
-+
-+import it.unimi.dsi.fastutil.PriorityQueue;
-+
-+/** A class providing static methods and objects that do useful things with priority queues.
-+ *
-+ * @see it.unimi.dsi.fastutil.PriorityQueue
-+ */
-+
-+public class PriorityQueues {
-+
-+	private PriorityQueues() {}
-+
-+	/** An immutable class representing the empty priority queue.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * {@link PriorityQueue}.
-+	 */
-+
-+	@SuppressWarnings("rawtypes")
-+	public static class EmptyPriorityQueue extends AbstractPriorityQueue {
-+
-+		protected EmptyPriorityQueue() {}
-+
-+		public void enqueue( Object o ) { throw new UnsupportedOperationException(); }
-+		public Object dequeue() { throw new NoSuchElementException(); }
-+		public boolean isEmpty() { return true; }
-+		public int size() { return 0; }
-+		public void clear() {}
-+		public Object first() { throw new NoSuchElementException(); }
-+		public Object last() { throw new NoSuchElementException(); }
-+		public void changed() { throw new NoSuchElementException(); }
-+		public Comparator<?> comparator() { return null; }
-+		
-+	}
-+
-+	/** An empty indirect priority queue (immutable).
-+	 */
-+
-+	public final static EmptyPriorityQueue EMPTY_QUEUE = new EmptyPriorityQueue();
-+
-+
-+	/** A synchronized wrapper class for priority queues. */
-+
-+	public static class SynchronizedPriorityQueue<K> implements PriorityQueue<K> {
-+		
-+		public static final long serialVersionUID = -7046029254386353129L;
-+
-+		final protected PriorityQueue <K> q;
-+		final protected Object sync;
-+
-+		protected SynchronizedPriorityQueue( final PriorityQueue <K> q, final Object sync ) {
-+			this.q = q;
-+			this.sync = sync;
-+		}
-+
-+		protected SynchronizedPriorityQueue( final PriorityQueue <K> q ) {
-+			this.q = q;
-+			this.sync = this;
-+		}
-+
-+		public void enqueue( K x ) { synchronized( sync ) { q.enqueue( x ); } }
-+		public K dequeue() { synchronized( sync ) { return q.dequeue(); } }
-+		public K first() { synchronized( sync ) { return q.first(); } }
-+		public K last() { synchronized( sync ) { return q.last(); } }
-+		public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
-+		public int size() { synchronized( sync ) { return q.size(); } }
-+		public void clear() { synchronized( sync ) { q.clear(); } }
-+		public void changed() { synchronized( sync ) { q.changed(); } }
-+		public Comparator <? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
-+	}
-+
-+
-+	/** Returns a synchronized priority queue backed by the specified priority queue.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+	public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q ) {	return new SynchronizedPriorityQueue<K>( q ); }
-+
-+	/** Returns a synchronized priority queue backed by the specified priority queue, using an assigned object to synchronize.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @param sync an object that will be used to synchronize the access to the priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+
-+	public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q, final Object sync ) { return new SynchronizedPriorityQueue<K>( q, sync ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Size64.java b/src/main/java/it/unimi/dsi/fastutil/Size64.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Size64.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2010-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+import java.util.Collection;
-+
-+/** An interface for data structures whose size can exceed {@link Integer#MAX_VALUE}.
-+ *
-+ * <P>The only methods specified by this interfaces are {@link #size64()}, and 
-+ * a deprecated {@link #size()} identical to {@link Collection#size()}. Implementations
-+ * can work around the type problem of {@link java.util.Collection#size()}
-+ * (e.g., not being able to return more than {@link Integer#MAX_VALUE}) by implementing this
-+ * interface. Callers interested in large structures
-+ * can use a reflective call to <code>instanceof</code> to check for the presence of {@link #size64()}.
-+ * 
-+ * <p>We remark that it is always a good idea to implement both {@link #size()} <em>and</em> {@link #size64()},
-+ * as the former might be implemented by a superclass in an incompatible way. If you implement this interface,
-+ * just implement {@link #size()} as a <em>deprecated</em> method returning <code>Math.min(Integer.MAX_VALUE, size64())</code>.
-+ */
-+
-+public interface Size64 {
-+	/** Returns the size of this data structure as a long.
-+	 *
-+	 * @return  the size of this data structure.
-+	 */
-+	long size64();
-+
-+	/** Returns the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
-+	 * 
-+	 * @return the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
-+	 * @see java.util.Collection#size()
-+	 * @deprecated Use {@link #size64()} instead.
-+	 */
-+	@Deprecated
-+	int size();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Stack.java b/src/main/java/it/unimi/dsi/fastutil/Stack.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Stack.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+
-+import java.util.NoSuchElementException;
-+
-+/** A stack.
-+ *
-+ * <P>A stack must provide the classical {@link #push(Object)} and 
-+ * {@link #pop()} operations, but may be also <em>peekable</em>
-+ * to some extent: it may provide just the {@link #top()} function,
-+ * or even a more powerful {@link #peek(int)} method that provides
-+ * access to all elements on the stack (indexed from the top, which
-+ * has index 0).
-+ */
-+
-+public interface Stack<K> {
-+
-+	/** Pushes the given object on the stack.
-+	 *
-+	 * @param o the object that will become the new top of the stack.
-+	 */
-+
-+	void push( K o );
-+
-+	/** Pops the top off the stack.
-+	 *
-+	 * @return the top of the stack.
-+	 * @throws NoSuchElementException if the stack is empty.
-+	 */
-+
-+	K pop();
-+
-+	/** Checks whether the stack is empty.
-+	 *
-+	 * @return true if the stack is empty.
-+	 */
-+
-+	boolean isEmpty();
-+
-+	/** Peeks at the top of the stack (optional operation).
-+	 *
-+	 * @return the top of the stack.
-+	 * @throws NoSuchElementException if the stack is empty.
-+	 */
-+
-+	K top();
-+
-+	/** Peeks at an element on the stack (optional operation).
-+	 *
-+	 * @param i an index from the stop of the stack (0 represents the top).
-+	 * @return the <code>i</code>-th element on the stack.
-+	 * @throws IndexOutOfBoundsException if the designated element does not exist..
-+	 */
-+
-+	K peek( int i );
-+
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/Swapper.java b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
-@@ -0,0 +0,0 @@
-+package it.unimi.dsi.fastutil;
-+
-+/*		 
-+ * Copyright (C) 2010-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ */
-+
-+/** An object that can swap elements whose position is specified by integers 
-+ *
-+ * @see Arrays#quickSort(int, int, it.unimi.dsi.fastutil.ints.IntComparator, Swapper)
-+ */
-+
-+public interface Swapper {
-+	/** Swaps the data at the given positions.
-+	 * 
-+	 * @param a the first position to swap.
-+	 * @param b the second position to swap.
-+	 */
-+	void swap( int a, int b );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** An abstract class providing basic methods for functions implementing a type-specific interface.
-+ *
-+ * <P>Optional operations just throw an {@link
-+ * UnsupportedOperationException}. Generic versions of accessors delegate to
-+ * the corresponding type-specific counterparts following the interface rules
-+ * (they take care of returning <code>null</code> on a missing key).
-+ *
-+ * <P>This class handles directly a default return
-+ * value (including {@linkplain #defaultReturnValue() methods to access
-+ * it}). Instances of classes inheriting from this class have just to return
-+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
-+ * is serialized.
-+ *
-+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
-+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
-+ *
-+ */
-+public abstract class AbstractInt2ObjectFunction <V> implements Int2ObjectFunction <V>, java.io.Serializable {
-+ private static final long serialVersionUID = -4940583368468432370L;
-+ protected AbstractInt2ObjectFunction() {}
-+ /**
-+	 * The default return value for <code>get()</code>, <code>put()</code> and
-+	 * <code>remove()</code>.  
-+	 */
-+ protected V defRetValue;
-+ public void defaultReturnValue( final V rv ) {
-+  defRetValue = rv;
-+ }
-+ public V defaultReturnValue() {
-+  return defRetValue;
-+ }
-+ public V put( int key, V value ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public V remove( int key ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public void clear() {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean containsKey( final Object ok ) {
-+  if ( ok == null ) return false;
-+  return containsKey( ((((Integer)(ok)).intValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 */
-+ public V get( final Object ok ) {
-+  if ( ok == null ) return null;
-+  final int k = ((((Integer)(ok)).intValue()));
-+  return containsKey( k ) ? (get( k )) : null;
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key. 
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 *
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V put( final Integer ok, final V ov ) {
-+  final int k = ((ok).intValue());
-+  final boolean containsKey = containsKey( k );
-+  final V v = put( k, (ov) );
-+  return containsKey ? (v) : null;
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key. 
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 */
-+ public V remove( final Object ok ) {
-+  if ( ok == null ) return null;
-+  final int k = ((((Integer)(ok)).intValue()));
-+  final boolean containsKey = containsKey( k );
-+  final V v = remove( k );
-+  return containsKey ? (v) : null;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import java.util.Iterator;
-+import java.util.Map;
-+/** An abstract class providing basic methods for maps implementing a type-specific interface.
-+ *
-+ * <P>Optional operations just throw an {@link
-+ * UnsupportedOperationException}. Generic versions of accessors delegate to
-+ * the corresponding type-specific counterparts following the interface rules
-+ * (they take care of returning <code>null</code> on a missing key).
-+ *
-+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
-+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
-+ * is particularly useful for those classes that do not implement their own
-+ * entries (e.g., most immutable maps).
-+ */
-+public abstract class AbstractInt2ObjectMap <V> extends AbstractInt2ObjectFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
-+ private static final long serialVersionUID = -4940583368468432370L;
-+ protected AbstractInt2ObjectMap() {}
-+ /** Checks whether the given value is contained in {@link #values()}. */
-+ public boolean containsValue( Object v ) {
-+  return values().contains( v );
-+ }
-+ /** Checks whether the given value is contained in {@link #keySet()}. */
-+ public boolean containsKey( int k ) {
-+  return keySet().contains( k );
-+ }
-+ /** Puts all pairs in the given map.
-+	 * If the map implements the interface of this map,
-+	 * it uses the faster iterators.
-+	 *
-+	 * @param m a map.
-+	 */
-+  @SuppressWarnings({"unchecked","deprecation"})
-+ public void putAll(Map<? extends Integer,? extends V> m) {
-+  int n = m.size();
-+  final Iterator<? extends Map.Entry<? extends Integer,? extends V>> i = m.entrySet().iterator();
-+  if (m instanceof Int2ObjectMap) {
-+   Int2ObjectMap.Entry <? extends V> e;
-+   while(n-- != 0) {
-+    e = (Int2ObjectMap.Entry <? extends V>)i.next();
-+    put(e.getIntKey(), e.getValue());
-+   }
-+  }
-+  else {
-+   Map.Entry<? extends Integer,? extends V> e;
-+   while(n-- != 0) {
-+    e = i.next();
-+    put(e.getKey(), e.getValue());
-+   }
-+  }
-+ }
-+ public boolean isEmpty() {
-+  return size() == 0;
-+ }
-+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
-+	 * that do not have entries on their own (e.g., most immutable maps). 
-+	 *
-+	 * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
-+	 * would not be reflected in the base map.
-+	 */
-+ public static class BasicEntry <V> implements Int2ObjectMap.Entry <V> {
-+  protected int key;
-+  protected V value;
-+  public BasicEntry( final Integer key, final V value ) {
-+   this.key = ((key).intValue());
-+   this.value = (value);
-+  }
-+  public BasicEntry( final int key, final V value ) {
-+   this.key = key;
-+   this.value = value;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key));
-+  }
-+  public int getIntKey() {
-+   return key;
-+  }
-+  public V getValue() {
-+   return (value);
-+  }
-+  public V setValue( final V value ) {
-+   throw new UnsupportedOperationException();
-+  }
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-+   return ( (key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
-+  }
-+  public String toString() {
-+   return key + "->" + value;
-+  }
-+ }
-+ /** Returns a type-specific-set view of the keys of this map.
-+	 *
-+	 * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public IntSet keySet() {
-+  return new AbstractIntSet () {
-+    public boolean contains( final int k ) { return containsKey( k ); }
-+    public int size() { return AbstractInt2ObjectMap.this.size(); }
-+    public void clear() { AbstractInt2ObjectMap.this.clear(); }
-+    public IntIterator iterator() {
-+     return new AbstractIntIterator () {
-+       final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
-+       /** {@inheritDoc}
-+							 * @deprecated Please use the corresponding type-specific method instead. */
-+       @Deprecated
-+       public int nextInt() { return ((Int2ObjectMap.Entry <V>)i.next()).getIntKey(); };
-+       public boolean hasNext() { return i.hasNext(); }
-+      };
-+    }
-+   };
-+ }
-+ /** Returns a type-specific-set view of the values of this map.
-+	 *
-+	 * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public ObjectCollection <V> values() {
-+  return new AbstractObjectCollection <V>() {
-+    public boolean contains( final Object k ) { return containsValue( k ); }
-+    public int size() { return AbstractInt2ObjectMap.this.size(); }
-+    public void clear() { AbstractInt2ObjectMap.this.clear(); }
-+    public ObjectIterator <V> iterator() {
-+     return new AbstractObjectIterator <V>() {
-+       final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
-+       /** {@inheritDoc}
-+							 * @deprecated Please use the corresponding type-specific method instead. */
-+       @Deprecated
-+       public V next() { return ((Int2ObjectMap.Entry <V>)i.next()).getValue(); };
-+       public boolean hasNext() { return i.hasNext(); }
-+      };
-+    }
-+   };
-+ }
-+ @SuppressWarnings({ "unchecked", "rawtypes" })
-+ public ObjectSet<Map.Entry<Integer, V>> entrySet() {
-+  return (ObjectSet)int2ObjectEntrySet();
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * The hash code of a map is computed by summing the hash codes of its entries.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0, n = size();
-+  final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
-+  while( n-- != 0 ) h += i.next().hashCode();
-+  return h;
-+ }
-+ public boolean equals(Object o) {
-+  if ( o == this ) return true;
-+  if ( ! ( o instanceof Map ) ) return false;
-+  Map<?,?> m = (Map<?,?>)o;
-+  if ( m.size() != size() ) return false;
-+  return entrySet().containsAll( m.entrySet() );
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
-+  int n = size();
-+  Int2ObjectMap.Entry <V> e;
-+  boolean first = true;
-+  s.append("{");
-+  while(n-- != 0) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   e = (Int2ObjectMap.Entry <V>)i.next();
-+    s.append(String.valueOf(e.getIntKey()));
-+   s.append("=>");
-+   if (this == e.getValue()) s.append("(this map)"); else
-+    s.append(String.valueOf(e.getValue()));
-+  }
-+  s.append("}");
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import java.util.Map;
-+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
-+public abstract class AbstractInt2ObjectSortedMap <V> extends AbstractInt2ObjectMap <V> implements Int2ObjectSortedMap <V> {
-+ private static final long serialVersionUID = -1773560792952436569L;
-+ protected AbstractInt2ObjectSortedMap() {}
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Int2ObjectSortedMap <V> headMap( final Integer to ) {
-+  return headMap( ((to).intValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Int2ObjectSortedMap <V> tailMap( final Integer from ) {
-+  return tailMap( ((from).intValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) {
-+  return subMap( ((from).intValue()), ((to).intValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer firstKey() {
-+  return (Integer.valueOf(firstIntKey()));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer lastKey() {
-+  return (Integer.valueOf(lastIntKey()));
-+ }
-+ /** Returns a type-specific-sorted-set view of the keys of this map.
-+	 *
-+	 * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public IntSortedSet keySet() {
-+  return new KeySet();
-+ }
-+ /** A wrapper exhibiting the keys of a map. */
-+ protected class KeySet extends AbstractIntSortedSet {
-+  public boolean contains( final int k ) { return containsKey( k ); }
-+  public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
-+  public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
-+  public IntComparator comparator() { return AbstractInt2ObjectSortedMap.this.comparator(); }
-+  public int firstInt() { return firstIntKey(); }
-+  public int lastInt() { return lastIntKey(); }
-+  public IntSortedSet headSet( final int to ) { return headMap( to ).keySet(); }
-+  public IntSortedSet tailSet( final int from ) { return tailMap( from ).keySet(); }
-+  public IntSortedSet subSet( final int from, final int to ) { return subMap( from, to ).keySet(); }
-+  public IntBidirectionalIterator iterator( final int from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
-+  public IntBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
-+ }
-+ /** A wrapper exhibiting a map iterator as an iterator on keys.
-+	 *
-+	 * <P>To provide an iterator on keys, just create an instance of this
-+	 * class using the corresponding iterator on entries.
-+	 */
-+ protected static class KeySetIterator <V> extends AbstractIntBidirectionalIterator {
-+  protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
-+  public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
-+   this.i = i;
-+  }
-+  public int nextInt() { return ((i.next().getKey()).intValue()); };
-+  public int previousInt() { return ((i.previous().getKey()).intValue()); };
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+ }
-+ /** Returns a type-specific collection view of the values contained in this map.
-+	 *
-+	 * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a type-specific collection view of the values contained in this map.
-+	 */
-+ public ObjectCollection <V> values() {
-+  return new ValuesCollection();
-+ }
-+ /** A wrapper exhibiting the values of a map. */
-+ protected class ValuesCollection extends AbstractObjectCollection <V> {
-+  public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
-+  public boolean contains( final Object k ) { return containsValue( k ); }
-+  public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
-+  public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
-+ }
-+ /** A wrapper exhibiting a map iterator as an iterator on values.
-+	 *
-+	 * <P>To provide an iterator on values, just create an instance of this
-+	 * class using the corresponding iterator on entries.
-+	 */
-+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
-+  protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
-+  public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
-+   this.i = i;
-+  }
-+  public V next() { return (i.next().getValue()); };
-+  public boolean hasNext() { return i.hasNext(); }
-+ }
-+ @SuppressWarnings({ "unchecked", "rawtypes" })
-+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() {
-+  return (ObjectSortedSet)int2ObjectEntrySet();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
-+ *
-+ * <P>To create a type-specific bidirectional iterator, besides what is needed
-+ * for an iterator you need both a method returning the previous element as
-+ * primitive type and a method returning the previous element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #back(int)} that
-+ * uses type-specific methods.
-+ */
-+public abstract class AbstractIntBidirectionalIterator extends AbstractIntIterator implements IntBidirectionalIterator {
-+ protected AbstractIntBidirectionalIterator() {}
-+ /** Delegates to the corresponding generic method. */
-+ public int previousInt() { return previous().intValue(); }
-+ /** Delegates to the corresponding type-specific method. */
-+ public Integer previous() { return Integer.valueOf( previousInt() ); }
-+ /** This method just iterates the type-specific version of {@link #previous()} for
-+	 * at most <code>n</code> times, stopping if {@link
-+	 * #hasPrevious()} becomes false. */
-+ public int back( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasPrevious() ) previousInt();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.AbstractCollection;
-+import java.util.Collection;
-+import java.util.Iterator;
-+/** An abstract class providing basic methods for collections implementing a type-specific interface.
-+ *
-+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
-+ * {@link #contains(Object)} methods that just call the type-specific counterpart. 
-+ */
-+public abstract class AbstractIntCollection extends AbstractCollection<Integer> implements IntCollection {
-+ protected AbstractIntCollection() {}
-+ public int[] toArray( int a[] ) {
-+  return toIntArray( a );
-+ }
-+ public int[] toIntArray() {
-+  return toIntArray( null );
-+ }
-+ public int[] toIntArray( int a[] ) {
-+  if ( a == null || a.length < size() ) a = new int[ size() ];
-+  IntIterators.unwrap( iterator(), a );
-+  return a;
-+ }
-+ /** Adds all elements of the given type-specific collection to this collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean addAll( IntCollection c ) {
-+  boolean retVal = false;
-+  final IntIterator i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( add( i.nextInt() ) ) retVal = true;
-+  return retVal;
-+ }
-+ /** Checks whether this collection contains all elements from the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection contains all elements of the argument.
-+	 */
-+ public boolean containsAll( IntCollection c ) {
-+  final IntIterator i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( ! contains( i.nextInt() ) ) return false;
-+  return true;
-+ }
-+ /** Retains in this collection only elements from the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean retainAll( IntCollection c ) {
-+  boolean retVal = false;
-+  int n = size();
-+  final IntIterator i = iterator();
-+  while( n-- != 0 ) {
-+   if ( ! c.contains( i.nextInt() ) ) {
-+    i.remove();
-+    retVal = true;
-+   }
-+  }
-+  return retVal;
-+ }
-+ /** Remove from this collection all elements in the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean removeAll( IntCollection c ) {
-+  boolean retVal = false;
-+  int n = c.size();
-+  final IntIterator i = c.iterator();
-+  while( n-- != 0 ) if ( rem( i.nextInt() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public Object[] toArray() {
-+  final Object[] a = new Object[ size() ];
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  return a;
-+ }
-+ @SuppressWarnings("unchecked")
-+ public <T> T[] toArray( T[] a ) {
-+  final int size = size();
-+  if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  if ( size < a.length ) a[ size ] = null;
-+  return a;
-+ }
-+ /** Adds all elements of the given collection to this collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean addAll( Collection<? extends Integer> c ) {
-+  boolean retVal = false;
-+  final Iterator<? extends Integer> i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean add( int k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public IntIterator intIterator() {
-+  return iterator();
-+ }
-+ public abstract IntIterator iterator();
-+ /** Delegates to the type-specific <code>rem()</code> method. */
-+ public boolean remove( Object ok ) {
-+  if ( ok == null ) return false;
-+  return rem( ((((Integer)(ok)).intValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean add( final Integer o ) {
-+  return add( o.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean rem( final Object o ) {
-+  if ( o == null ) return false;
-+  return rem( ((((Integer)(o)).intValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean contains( final Object o ) {
-+  if ( o == null ) return false;
-+  return contains( ((((Integer)(o)).intValue())) );
-+ }
-+ public boolean contains( final int k ) {
-+  final IntIterator iterator = iterator();
-+  while ( iterator.hasNext() ) if ( k == iterator.nextInt() ) return true;
-+        return false;
-+    }
-+ public boolean rem( final int k ) {
-+  final IntIterator iterator = iterator();
-+  while ( iterator.hasNext() )
-+   if ( k == iterator.nextInt() ) {
-+    iterator.remove();
-+    return true;
-+   }
-+        return false;
-+    }
-+ /** Checks whether this collection contains all elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection contains all elements of the argument.
-+	 */
-+ public boolean containsAll( Collection<?> c ) {
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
-+  return true;
-+ }
-+ /** Retains in this collection only elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean retainAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = size();
-+  final Iterator<?> i = iterator();
-+  while( n-- != 0 ) {
-+   if ( ! c.contains( i.next() ) ) {
-+    i.remove();
-+    retVal = true;
-+   }
-+  }
-+  return retVal;
-+ }
-+ /** Remove from this collection all elements in the given collection.
-+	 * If the collection is an instance of this class, it uses faster iterators.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean removeAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean isEmpty() {
-+  return size() == 0;
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final IntIterator i = iterator();
-+  int n = size();
-+  int k;
-+  boolean first = true;
-+  s.append("{");
-+  while(n-- != 0) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.nextInt();
-+    s.append(String.valueOf(k));
-+  }
-+  s.append("}");
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
-+ *
-+ * <P>To create a type-specific comparator you need both a method comparing
-+ * primitive types and a method comparing objects. However, if you have the
-+ * first one you can just inherit from this class and get for free the second
-+ * one.
-+ * 
-+ * @see java.util.Comparator
-+ */
-+public abstract class AbstractIntComparator implements IntComparator , java.io.Serializable {
-+    private static final long serialVersionUID = 0L;
-+ protected AbstractIntComparator() {}
-+ public int compare( Integer ok1, Integer ok2 ) {
-+  return compare( ok1.intValue(), ok2.intValue() );
-+ }
-+ public abstract int compare( int k1, int k2 );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/**  An abstract class facilitating the creation of type-specific iterators.
-+ *
-+ * <P>To create a type-specific iterator you need both a method returning the
-+ * next element as primitive type and a method returning the next element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
-+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
-+ * UnsupportedOperationException}.
-+ *
-+ * @see java.util.Iterator
-+ */
-+public abstract class AbstractIntIterator implements IntIterator {
-+ protected AbstractIntIterator() {}
-+ /** Delegates to the corresponding generic method. */
-+ public int nextInt() { return next().intValue(); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer next() { return Integer.valueOf( nextInt() ); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void remove() { throw new UnsupportedOperationException(); }
-+ /** This method just iterates the type-specific version of {@link #next()} for at most
-+	 * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
-+ public int skip( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasNext() ) nextInt();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.List;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/**  An abstract class providing basic methods for lists implementing a type-specific list interface.
-+ *
-+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
-+ */
-+public abstract class AbstractIntList extends AbstractIntCollection implements IntList , IntStack {
-+ protected AbstractIntList() {}
-+ /** Ensures that the given index is nonnegative and not greater than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
-+	 */
-+ protected void ensureIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
-+ }
-+ /** Ensures that the given index is nonnegative and smaller than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
-+	 */
-+ protected void ensureRestrictedIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
-+ }
-+ public void add( final int index, final int k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean add( final int k ) {
-+  add( size(), k );
-+  return true;
-+ }
-+ public int removeInt( int i ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public int set( final int index, final int k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean addAll( int index, final Collection<? extends Integer> c ) {
-+  ensureIndex( index );
-+  int n = c.size();
-+  if ( n == 0 ) return false;
-+  Iterator<? extends Integer> i = c.iterator();
-+  while( n-- != 0 ) add( index++, i.next() );
-+  return true;
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final Collection<? extends Integer> c ) {
-+  return addAll( size(), c );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public IntListIterator intListIterator() {
-+  return listIterator();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public IntListIterator intListIterator( final int index ) {
-+  return listIterator( index );
-+ }
-+ public IntListIterator iterator() {
-+  return listIterator();
-+ }
-+ public IntListIterator listIterator() {
-+  return listIterator( 0 );
-+ }
-+ public IntListIterator listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractIntListIterator () {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < AbstractIntList.this.size(); }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = pos++ ); }
-+    public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = --pos ); }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( int k ) {
-+     AbstractIntList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( int k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractIntList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractIntList.this.removeInt( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public boolean contains( final int k ) {
-+  return indexOf( k ) >= 0;
-+ }
-+ public int indexOf( final int k ) {
-+  final IntListIterator i = listIterator();
-+  int e;
-+  while( i.hasNext() ) {
-+   e = i.nextInt();
-+   if ( ( (k) == (e) ) ) return i.previousIndex();
-+  }
-+  return -1;
-+ }
-+ public int lastIndexOf( final int k ) {
-+  IntListIterator i = listIterator( size() );
-+  int e;
-+  while( i.hasPrevious() ) {
-+   e = i.previousInt();
-+   if ( ( (k) == (e) ) ) return i.nextIndex();
-+  }
-+  return -1;
-+ }
-+ public void size( final int size ) {
-+  int i = size();
-+  if ( size > i ) while( i++ < size ) add( (0) );
-+  else while( i-- != size ) remove( i );
-+ }
-+ public IntList subList( final int from, final int to ) {
-+  ensureIndex( from );
-+  ensureIndex( to );
-+  if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  return new IntSubList ( this, from, to );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public IntList intSubList( final int from, final int to ) {
-+  return subList( from, to );
-+ }
-+ /** Removes elements of this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  ensureIndex( to );
-+  IntListIterator i = listIterator( from );
-+  int n = to - from;
-+  if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  while( n-- != 0 ) {
-+   i.nextInt();
-+   i.remove();
-+  }
-+ }
-+ /** Adds elements to this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( int index, final int a[], int offset, int length ) {
-+  ensureIndex( index );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  while( length-- != 0 ) add( index++, a[ offset++ ] );
-+ }
-+ public void addElements( final int index, final int a[] ) {
-+  addElements( index, a, 0, a.length );
-+ }
-+ /** Copies element of this type-specific list into the given array one-by-one.
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final int a[], int offset, int length ) {
-+  IntListIterator i = listIterator( from );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
-+  while( length-- != 0 ) a[ offset++ ] = i.nextInt();
-+ }
-+ private boolean valEquals( final Object a, final Object b ) {
-+  return a == null ? b == null : a.equals( b );
-+ }
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( ! ( o instanceof List ) ) return false;
-+  final List<?> l = (List<?>)o;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  if ( l instanceof IntList ) {
-+   final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
-+   while( s-- != 0 ) if ( i1.nextInt() != i2.nextInt() ) return false;
-+   return true;
-+  }
-+  final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
-+  while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
-+  return true;
-+ }
-+    /** Compares this list to another object. If the
-+     * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
-+     * it throws a <code>ClassCastException</code>.
-+     *
-+     * @param l a list.
-+     * @return if the argument is a {@link java.util.List}, a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     * @throws ClassCastException if the argument is not a list.
-+     */
-+
-+ public int compareTo( final List<? extends Integer> l ) {
-+  if ( l == this ) return 0;
-+  if ( l instanceof IntList ) {
-+   final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
-+   int r;
-+   int e1, e2;
-+   while( i1.hasNext() && i2.hasNext() ) {
-+    e1 = i1.nextInt();
-+    e2 = i2.nextInt();
-+    if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
-+   }
-+   return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+  }
-+  ListIterator<? extends Integer> i1 = listIterator(), i2 = l.listIterator();
-+  int r;
-+  while( i1.hasNext() && i2.hasNext() ) {
-+   if ( ( r = ((Comparable<? super Integer>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
-+  }
-+  return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+ }
-+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
-+	 *
-+	 * @return the hash code for this list.
-+	 */
-+ public int hashCode() {
-+  IntIterator i = iterator();
-+  int h = 1, s = size();
-+  while ( s-- != 0 ) {
-+   int k = i.nextInt();
-+   h = 31 * h + (k);
-+  }
-+  return h;
-+ }
-+ public void push( int o ) {
-+  add( o );
-+ }
-+ public int popInt() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return removeInt( size() - 1 );
-+ }
-+ public int topInt() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return getInt( size() - 1 );
-+ }
-+ public int peekInt( int i ) {
-+  return getInt( size() - 1 - i );
-+ }
-+ public boolean rem( int k ) {
-+  int index = indexOf( k );
-+  if ( index == -1 ) return false;
-+  removeInt( index );
-+  return true;
-+ }
-+ /** Delegates to <code>rem()</code>. */
-+ public boolean remove( final Object o ) {
-+  return rem( ((((Integer)(o)).intValue())) );
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final int index, final IntCollection c ) {
-+  return addAll( index, (Collection<? extends Integer>)c );
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final int index, final IntList l ) {
-+  return addAll( index, (IntCollection)l );
-+ }
-+ public boolean addAll( final IntCollection c ) {
-+  return addAll( size(), c );
-+ }
-+ public boolean addAll( final IntList l ) {
-+  return addAll( size(), l );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void add( final int index, final Integer ok ) {
-+  add( index, ok.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer set( final int index, final Integer ok ) {
-+  return (Integer.valueOf(set( index, ok.intValue() )));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer get( final int index ) {
-+  return (Integer.valueOf(getInt( index )));
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public int indexOf( final Object ok) {
-+  return indexOf( ((((Integer)(ok)).intValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public int lastIndexOf( final Object ok ) {
-+  return lastIndexOf( ((((Integer)(ok)).intValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer remove( final int index ) {
-+  return (Integer.valueOf(removeInt( index )));
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void push( Integer o ) {
-+  push( o.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer pop() {
-+  return Integer.valueOf( popInt() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer top() {
-+  return Integer.valueOf( topInt() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer peek( int i ) {
-+  return Integer.valueOf( peekInt( i ) );
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final IntIterator i = iterator();
-+  int n = size();
-+  int k;
-+  boolean first = true;
-+  s.append("[");
-+  while( n-- != 0 ) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.nextInt();
-+    s.append( String.valueOf( k ) );
-+  }
-+  s.append("]");
-+  return s.toString();
-+ }
-+ public static class IntSubList extends AbstractIntList implements java.io.Serializable {
-+     private static final long serialVersionUID = -7046029254386353129L;
-+  /** The list this sublist restricts. */
-+  protected final IntList l;
-+  /** Initial (inclusive) index of this sublist. */
-+  protected final int from;
-+  /** Final (exclusive) index of this sublist. */
-+  protected int to;
-+  private static final boolean ASSERTS = false;
-+  public IntSubList( final IntList l, final int from, final int to ) {
-+   this.l = l;
-+   this.from = from;
-+   this.to = to;
-+  }
-+  private void assertRange() {
-+   if ( ASSERTS ) {
-+    assert from <= l.size();
-+    assert to <= l.size();
-+    assert to >= from;
-+   }
-+  }
-+  public boolean add( final int k ) {
-+   l.add( to, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+   return true;
-+  }
-+  public void add( final int index, final int k ) {
-+   ensureIndex( index );
-+   l.add( from + index, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public boolean addAll( final int index, final Collection<? extends Integer> c ) {
-+   ensureIndex( index );
-+   to += c.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = l.addAll( from + index, c );
-+    assertRange();
-+    return retVal;
-+   }
-+   return l.addAll( from + index, c );
-+  }
-+  public int getInt( int index ) {
-+   ensureRestrictedIndex( index );
-+   return l.getInt( from + index );
-+  }
-+  public int removeInt( int index ) {
-+   ensureRestrictedIndex( index );
-+   to--;
-+   return l.removeInt( from + index );
-+  }
-+  public int set( int index, int k ) {
-+   ensureRestrictedIndex( index );
-+   return l.set( from + index, k );
-+  }
-+  public void clear() {
-+   removeElements( 0, size() );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public int size() {
-+   return to - from;
-+  }
-+  public void getElements( final int from, final int[] a, final int offset, final int length ) {
-+   ensureIndex( from );
-+   if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
-+   l.getElements( this.from + from, a, offset, length );
-+  }
-+  public void removeElements( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   l.removeElements( this.from + from, this.from + to );
-+   this.to -= ( to - from );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public void addElements( int index, final int a[], int offset, int length ) {
-+   ensureIndex( index );
-+   l.addElements( this.from + index, a, offset, length );
-+   this.to += length;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public IntListIterator listIterator( final int index ) {
-+   ensureIndex( index );
-+   return new AbstractIntListIterator () {
-+     int pos = index, last = -1;
-+     public boolean hasNext() { return pos < size(); }
-+     public boolean hasPrevious() { return pos > 0; }
-+     public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getInt( from + ( last = pos++ ) ); }
-+     public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getInt( from + ( last = --pos ) ); }
-+     public int nextIndex() { return pos; }
-+     public int previousIndex() { return pos - 1; }
-+     public void add( int k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      IntSubList.this.add( pos++, k );
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+     public void set( int k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      IntSubList.this.set( last, k );
-+     }
-+     public void remove() {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      IntSubList.this.removeInt( last );
-+      /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+      if ( last < pos ) pos--;
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+    };
-+  }
-+  public IntList subList( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+   return new IntSubList ( this, from, to );
-+  }
-+  public boolean rem( int k ) {
-+   int index = indexOf( k );
-+   if ( index == -1 ) return false;
-+   to--;
-+   l.removeInt( from + index );
-+   if ( ASSERTS ) assertRange();
-+   return true;
-+  }
-+  public boolean remove( final Object o ) {
-+   return rem( ((((Integer)(o)).intValue())) );
-+  }
-+  public boolean addAll( final int index, final IntCollection c ) {
-+   ensureIndex( index );
-+   to += c.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = l.addAll( from + index, c );
-+    assertRange();
-+    return retVal;
-+   }
-+   return l.addAll( from + index, c );
-+  }
-+  public boolean addAll( final int index, final IntList l ) {
-+   ensureIndex( index );
-+   to += l.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = this.l.addAll( from + index, l );
-+    assertRange();
-+    return retVal;
-+   }
-+   return this.l.addAll( from + index, l );
-+  }
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
-+ *
-+ * <P>This class provides trivial type-specific implementations of {@link
-+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
-+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
-+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
-+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
-+ * 
-+ *
-+ * @see java.util.ListIterator
-+ */
-+public abstract class AbstractIntListIterator extends AbstractIntBidirectionalIterator implements IntListIterator {
-+ protected AbstractIntListIterator() {}
-+ /** Delegates to the corresponding type-specific method. */
-+ public void set( Integer ok ) { set( ok.intValue() ); }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void add( Integer ok ) { add( ok.intValue() ); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void set( int k ) { throw new UnsupportedOperationException(); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void add( int k ) { throw new UnsupportedOperationException(); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
-+/**  An abstract class providing basic methods for priority queues implementing a type-specific interface.
-+ *
-+ */
-+public abstract class AbstractIntPriorityQueue extends AbstractPriorityQueue<Integer> implements java.io.Serializable, IntPriorityQueue {
-+ private static final long serialVersionUID = 1L;
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public void enqueue( final Integer x ) { enqueue( x.intValue() ); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer dequeue() { return (Integer.valueOf(dequeueInt())); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer first() { return (Integer.valueOf(firstInt())); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer last() { return (Integer.valueOf(lastInt())); }
-+ /** Throws an {@link UnsupportedOperationException}. */
-+ public int lastInt() { throw new UnsupportedOperationException(); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Set;
-+/**  An abstract class providing basic methods for sets implementing a type-specific interface. */
-+public abstract class AbstractIntSet extends AbstractIntCollection implements Cloneable, IntSet {
-+ protected AbstractIntSet() {}
-+ public abstract IntIterator iterator();
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( !( o instanceof Set ) ) return false;
-+  Set<?> s = (Set<?>) o;
-+  if ( s.size() != size() ) return false;
-+  return containsAll(s);
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * The hash code of a set is computed by summing the hash codes of
-+	 * its elements.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0, n = size();
-+  IntIterator i = iterator();
-+  int k;
-+  while( n-- != 0 ) {
-+   k = i.nextInt(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
-+   h += (k);
-+  }
-+  return h;
-+ }
-+ public boolean remove( int k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ /** Delegates to <code>remove()</code>.
-+	 *
-+	 * @param k the element to be removed.
-+	 * @return true if the set was modified.
-+	 */
-+ public boolean rem( int k ) {
-+  return remove( k );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean remove( final Object o ) {
-+  return remove( ((((Integer)(o)).intValue())) );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
-+public abstract class AbstractIntSortedSet extends AbstractIntSet implements IntSortedSet {
-+ protected AbstractIntSortedSet() {}
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public IntSortedSet headSet( final Integer to ) {
-+  return headSet( to.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public IntSortedSet tailSet( final Integer from ) {
-+  return tailSet( from.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public IntSortedSet subSet( final Integer from, final Integer to ) {
-+  return subSet( from.intValue(), to.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer first() {
-+  return (Integer.valueOf(firstInt()));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Integer last() {
-+  return (Integer.valueOf(lastInt()));
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public IntBidirectionalIterator intIterator() {
-+  return iterator();
-+ }
-+ public abstract IntBidirectionalIterator iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.AbstractStack;
-+/** An abstract class providing basic methods for implementing a type-specific stack interface.
-+ *
-+ * <P>To create a type-specific stack, you need both object methods and
-+ * primitive-type methods. However, if you inherit from this class you need
-+ * just one (anyone).
-+ */
-+public abstract class AbstractIntStack extends AbstractStack<Integer> implements IntStack {
-+ protected AbstractIntStack() {}
-+ /** Delegates to the corresponding type-specific method. */
-+ public void push( Integer o ) {
-+  push( o.intValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public Integer pop() {
-+  return Integer.valueOf( popInt() );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public Integer top() {
-+  return Integer.valueOf( topInt() );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public Integer peek( int i ) {
-+  return Integer.valueOf( peekInt( i ) );
-+ }
-+ /** Delegates to the corresponding generic method. */
-+ public void push( int k ) {
-+  push( Integer.valueOf( k ) );
-+ }
-+ /** Delegates to the corresponding generic method. */
-+ public int popInt() {
-+  return pop().intValue();
-+ }
-+ /** Delegates to the corresponding generic method. */
-+ public int topInt() {
-+  return top().intValue();
-+ }
-+ /** Delegates to the corresponding generic method. */
-+ public int peekInt( int i ) {
-+  return peek( i ).intValue();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Comparator;
-+import java.util.Iterator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+import java.util.NoSuchElementException;
-+/** A type-specific AVL tree map with a fast, small-footprint implementation.
-+ *
-+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
-+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
-+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
-+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
-+ */
-+public class Int2ObjectAVLTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
-+ /** A reference to the root entry. */
-+ protected transient Entry <V> tree;
-+ /** Number of entries in this map. */
-+ protected int count;
-+ /** The first key in this map. */
-+ protected transient Entry <V> firstEntry;
-+ /** The last key in this map. */
-+ protected transient Entry <V> lastEntry;
-+ /** Cached set of entries. */
-+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
-+ /** Cached set of keys. */
-+ protected transient IntSortedSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** The value of this variable remembers, after a <code>put()</code> 
-+	 * or a <code>remove()</code>, whether the <em>domain</em> of the map
-+	 * has been modified. */
-+ protected transient boolean modified;
-+ /** This map's comparator, as provided in the constructor. */
-+ protected Comparator<? super Integer> storedComparator;
-+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
-+		always a type-specific comparator, so it could be derived from the former by wrapping. */
-+ protected transient IntComparator actualComparator;
-+ private static final long serialVersionUID = -7046029254386353129L;
-+ private static final boolean ASSERTS = false;
-+ {
-+  allocatePaths();
-+ }
-+ /** Creates a new empty tree map. 
-+	 */
-+ public Int2ObjectAVLTreeMap() {
-+  tree = null;
-+  count = 0;
-+ }
-+ /** Generates the comparator that will be actually used.
-+	 *
-+	 * <P>When a specific {@link Comparator} is specified and stored in {@link
-+	 * #storedComparator}, we must check whether it is type-specific.  If it is
-+	 * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
-+	 * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
-+	 * and makes it into a type-specific one.
-+	 */
-+ private void setActualComparator() {
-+  /* If the provided comparator is already type-specific, we use it. Otherwise,
-+		   we use a wrapper anonymous class to fake that it is type-specific. */
-+  if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
-+  else actualComparator = new IntComparator () {
-+    public int compare( int k1, int k2 ) {
-+     return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
-+    }
-+    public int compare( Integer ok1, Integer ok2 ) {
-+     return storedComparator.compare( ok1, ok2 );
-+    }
-+   };
-+ }
-+ /** Creates a new empty tree map with the given comparator.
-+	 *
-+	 * @param c a (possibly type-specific) comparator.
-+	 */
-+ public Int2ObjectAVLTreeMap( final Comparator<? super Integer> c ) {
-+  this();
-+  storedComparator = c;
-+  setActualComparator();
-+ }
-+ /** Creates a new tree map copying a given map.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectAVLTreeMap( final Map<? extends Integer, ? extends V> m ) {
-+  this();
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
-+	 *
-+	 * @param m a {@link SortedMap} to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectAVLTreeMap( final SortedMap<Integer,V> m ) {
-+  this( m.comparator() );
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given map.
-+	 *
-+	 * @param m a type-specific map to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectAVLTreeMap( final Int2ObjectMap <? extends V> m ) {
-+  this();
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
-+	 *
-+	 * @param m a type-specific sorted map to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectAVLTreeMap( final Int2ObjectSortedMap <V> m ) {
-+  this( m.comparator() );
-+  putAll( m );
-+ }
-+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
-+	 *
-+	 * @param k the array of keys of the new tree map.
-+	 * @param v the array of corresponding values in the new tree map.
-+	 * @param c a (possibly type-specific) comparator.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectAVLTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
-+  this( c );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new tree map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new tree map.
-+	 * @param v the array of corresponding values in the new tree map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectAVLTreeMap( final int[] k, final V v[] ) {
-+  this( k, v, null );
-+ }
-+ /*
-+	 * The following methods implements some basic building blocks used by
-+	 * all accessors.  They are (and should be maintained) identical to those used in AVLTreeSet.drv.
-+	 *
-+	 * The put()/remove() code is derived from Ben Pfaff's GNU libavl
-+	 * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
-+	 * going on, you should have a look at the literate code contained therein
-+	 * first.  
-+	 */
-+ /** Compares two keys in the right way. 
-+	 *
-+	 * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
-+	 * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
-+	 *
-+	 * @param k1 the first key.
-+	 * @param k2 the second key.
-+	 * @return a number smaller than, equal to or greater than 0, as usual
-+	 * (i.e., when k1 &lt; k2, k1 = k2 or k1 &gt; k2, respectively).
-+	 */
-+
-+ final int compare( final int k1, final int k2 ) {
-+  return actualComparator == null ? ( Integer.compare((k1),(k2)) ) : actualComparator.compare( k1, k2 );
-+ }
-+ /** Returns the entry corresponding to the given key, if it is in the tree; <code>null</code>, otherwise.
-+	 *
-+	 * @param k the key to search for.
-+	 * @return the corresponding entry, or <code>null</code> if no entry with the given key exists.
-+	 */
-+ final Entry <V> findKey( final int k ) {
-+  Entry <V> e = tree;
-+  int cmp;
-+  while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) e = cmp < 0 ? e.left() : e.right();
-+  return e;
-+ }
-+ /** Locates a key.
-+	 *
-+	 * @param k a key.
-+	 * @return the last entry on a search for the given key; this will be
-+	 * the given key, if it present; otherwise, it will be either the smallest greater key or the greatest smaller key.
-+	 */
-+ final Entry <V> locateKey( final int k ) {
-+  Entry <V> e = tree, last = tree;
-+  int cmp = 0;
-+  while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) {
-+   last = e;
-+   e = cmp < 0 ? e.left() : e.right();
-+  }
-+  return cmp == 0 ? e : last;
-+ }
-+ /** This vector remembers the directions followed during 
-+	 * the current insertion. It suffices for about 2<sup>32</sup> entries. */
-+ private transient boolean dirPath[];
-+ private void allocatePaths() {
-+  dirPath = new boolean[ 48 ];
-+ }
-+ public V put( final int k, final V v ) {
-+  Entry <V> e = add( k );
-+  final V oldValue = e.value;
-+  e.value = v;
-+  return oldValue;
-+ }
-+ /** Returns a node with key k in the balanced tree, creating one with defRetValue if necessary.
-+	*
-+	* @param k the key
-+	* @return a node with key k. If a node with key k already exists, then that node is returned,
-+	* 				otherwise a new node with defRetValue is created ensuring that the tree is balanced
-+						after creation of the node.
-+	*/
-+ private Entry <V> add( final int k ) {
-+   /* After execution of this method, modified is true iff a new entry has
-+  	been inserted. */
-+  modified = false;
-+  Entry <V> e = null;
-+  if ( tree == null ) { // The case of the empty tree is treated separately.
-+   count++;
-+   e = tree = lastEntry = firstEntry = new Entry <V>( k, defRetValue );
-+   modified = true;
-+  }
-+  else {
-+   Entry <V> p = tree, q = null, y = tree, z = null, w = null;
-+   int cmp, i = 0;
-+   while( true ) {
-+    if ( ( cmp = compare( k, p.key ) ) == 0 ) {
-+     return p;
-+    }
-+    if ( p.balance() != 0 ) {
-+     i = 0;
-+     z = q;
-+     y = p;
-+    }
-+    if ( dirPath[ i++ ] = cmp > 0 ) {
-+     if ( p.succ() ) {
-+      count++;
-+      e = new Entry <V>( k, defRetValue );
-+      modified = true;
-+      if ( p.right == null ) lastEntry = e;
-+      e.left = p;
-+      e.right = p.right;
-+      p.right( e );
-+      break;
-+     }
-+     q = p;
-+     p = p.right;
-+    }
-+    else {
-+     if ( p.pred() ) {
-+      count++;
-+      e = new Entry <V>( k, defRetValue );
-+      modified = true;
-+      if ( p.left == null ) firstEntry = e;
-+      e.right = p;
-+      e.left = p.left;
-+      p.left( e );
-+      break;
-+     }
-+     q = p;
-+     p = p.left;
-+    }
-+   }
-+   p = y;
-+   i = 0;
-+   while( p != e ) {
-+    if ( dirPath[ i ] ) p.incBalance();
-+    else p.decBalance();
-+    p = dirPath[ i++ ] ? p.right : p.left;
-+   }
-+   if ( y.balance() == -2 ) {
-+    Entry <V> x = y.left;
-+    if ( x.balance() == -1 ) {
-+     w = x;
-+     if ( x.succ() ) {
-+      x.succ( false );
-+      y.pred( x );
-+     }
-+     else y.left = x.right;
-+     x.right = y;
-+     x.balance( 0 );
-+     y.balance( 0 );
-+    }
-+    else {
-+     if ( ASSERTS ) assert x.balance() == 1;
-+     w = x.right;
-+     x.right = w.left;
-+     w.left = x;
-+     y.left = w.right;
-+     w.right = y;
-+     if ( w.balance() == -1 ) {
-+      x.balance( 0 );
-+      y.balance( 1 );
-+     }
-+     else if ( w.balance() == 0 ) {
-+      x.balance( 0 );
-+      y.balance( 0 );
-+     }
-+     else {
-+      x.balance( -1 );
-+      y.balance( 0 );
-+     }
-+     w.balance( 0 );
-+     if ( w.pred() ) {
-+      x.succ( w );
-+      w.pred( false );
-+     }
-+     if ( w.succ() ) {
-+      y.pred( w );
-+      w.succ( false );
-+     }
-+    }
-+   }
-+   else if ( y.balance() == +2 ) {
-+    Entry <V> x = y.right;
-+    if ( x.balance() == 1 ) {
-+     w = x;
-+     if ( x.pred() ) {
-+      x.pred( false );
-+      y.succ( x );
-+     }
-+     else y.right = x.left;
-+     x.left = y;
-+     x.balance( 0 );
-+     y.balance( 0 );
-+    }
-+    else {
-+     if ( ASSERTS ) assert x.balance() == -1;
-+     w = x.left;
-+     x.left = w.right;
-+     w.right = x;
-+     y.right = w.left;
-+     w.left = y;
-+     if ( w.balance() == 1 ) {
-+      x.balance( 0 );
-+      y.balance( -1 );
-+     }
-+     else if ( w.balance() == 0 ) {
-+      x.balance( 0 );
-+      y.balance( 0 );
-+     }
-+     else {
-+      x.balance( 1 );
-+      y.balance( 0 );
-+     }
-+     w.balance( 0 );
-+     if ( w.pred() ) {
-+      y.succ( w );
-+      w.pred( false );
-+     }
-+     if ( w.succ() ) {
-+      x.pred( w );
-+      w.succ( false );
-+     }
-+    }
-+   }
-+   else return e;
-+   if ( z == null ) tree = w;
-+   else {
-+    if ( z.left == y ) z.left = w;
-+    else z.right = w;
-+   }
-+  }
-+  if ( ASSERTS ) checkTree( tree );
-+  return e;
-+ }
-+ /** Finds the parent of an entry.
-+	 *
-+	 * @param e a node of the tree.
-+	 * @return the parent of the given node, or <code>null</code> for the root.
-+	 */
-+ private Entry <V> parent( final Entry <V> e ) {
-+  if ( e == tree ) return null;
-+  Entry <V> x, y, p;
-+  x = y = e;
-+  while( true ) {
-+   if ( y.succ() ) {
-+    p = y.right;
-+    if ( p == null || p.left != e ) {
-+     while( ! x.pred() ) x = x.left;
-+     p = x.left;
-+    }
-+    return p;
-+   }
-+   else if ( x.pred() ) {
-+    p = x.left;
-+    if ( p == null || p.right != e ) {
-+     while( ! y.succ() ) y = y.right;
-+     p = y.right;
-+    }
-+    return p;
-+   }
-+   x = x.left;
-+   y = y.right;
-+  }
-+ }
-+ /* After execution of this method, {@link #modified} is true iff an entry
-+	has been deleted. */
-+
-+ public V remove( final int k ) {
-+  modified = false;
-+  if ( tree == null ) return defRetValue;
-+  int cmp;
-+  Entry <V> p = tree, q = null;
-+  boolean dir = false;
-+  final int kk = k;
-+  while( true ) {
-+   if ( ( cmp = compare( kk, p.key ) ) == 0 ) break;
-+   else if ( dir = cmp > 0 ) {
-+    q = p;
-+    if ( ( p = p.right() ) == null ) return defRetValue;
-+   }
-+   else {
-+    q = p;
-+    if ( ( p = p.left() ) == null ) return defRetValue;
-+   }
-+  }
-+  if ( p.left == null ) firstEntry = p.next();
-+  if ( p.right == null ) lastEntry = p.prev();
-+  if ( p.succ() ) {
-+   if ( p.pred() ) {
-+    if ( q != null ) {
-+     if ( dir ) q.succ( p.right );
-+     else q.pred( p.left );
-+    }
-+    else tree = dir ? p.right : p.left;
-+   }
-+   else {
-+    p.prev().right = p.right;
-+    if ( q != null ) {
-+     if ( dir ) q.right = p.left;
-+     else q.left = p.left;
-+    }
-+    else tree = p.left;
-+   }
-+  }
-+  else {
-+   Entry <V> r = p.right;
-+   if ( r.pred() ) {
-+    r.left = p.left;
-+    r.pred( p.pred() );
-+    if ( ! r.pred() ) r.prev().right = r;
-+    if ( q != null ) {
-+     if ( dir ) q.right = r;
-+     else q.left = r;
-+    }
-+    else tree = r;
-+    r.balance( p.balance() );
-+    q = r;
-+    dir = true;
-+   }
-+   else {
-+    Entry <V> s;
-+    while( true ) {
-+     s = r.left;
-+     if ( s.pred() ) break;
-+     r = s;
-+    }
-+    if ( s.succ() ) r.pred( s );
-+    else r.left = s.right;
-+    s.left = p.left;
-+    if ( ! p.pred() ) {
-+     p.prev().right = s;
-+     s.pred( false );
-+    }
-+    s.right = p.right;
-+    s.succ( false );
-+    if ( q != null ) {
-+     if ( dir ) q.right = s;
-+     else q.left = s;
-+    }
-+    else tree = s;
-+    s.balance( p.balance() );
-+    q = r;
-+    dir = false;
-+   }
-+  }
-+  Entry <V> y;
-+  while( q != null ) {
-+   y = q;
-+   q = parent( y );
-+   if ( ! dir ) {
-+    dir = q != null && q.left != y;
-+    y.incBalance();
-+    if ( y.balance() == 1 ) break;
-+    else if ( y.balance() == 2 ) {
-+     Entry <V> x = y.right;
-+     if ( ASSERTS ) assert x != null;
-+     if ( x.balance() == -1 ) {
-+      Entry <V> w;
-+      if ( ASSERTS ) assert x.balance() == -1;
-+      w = x.left;
-+      x.left = w.right;
-+      w.right = x;
-+      y.right = w.left;
-+      w.left = y;
-+      if ( w.balance() == 1 ) {
-+       x.balance( 0 );
-+       y.balance( -1 );
-+      }
-+      else if ( w.balance() == 0 ) {
-+       x.balance( 0 );
-+       y.balance( 0 );
-+      }
-+      else {
-+       if ( ASSERTS ) assert w.balance() == -1;
-+       x.balance( 1 );
-+       y.balance( 0 );
-+      }
-+      w.balance( 0 );
-+      if ( w.pred() ) {
-+       y.succ( w );
-+       w.pred( false );
-+      }
-+      if ( w.succ() ) {
-+       x.pred( w );
-+       w.succ( false );
-+      }
-+      if ( q != null ) {
-+       if ( dir ) q.right = w;
-+       else q.left = w;
-+      }
-+      else tree = w;
-+     }
-+     else {
-+      if ( q != null ) {
-+       if ( dir ) q.right = x;
-+       else q.left = x;
-+      }
-+      else tree = x;
-+      if ( x.balance() == 0 ) {
-+       y.right = x.left;
-+       x.left = y;
-+       x.balance( -1 );
-+       y.balance( +1 );
-+       break;
-+      }
-+      if ( ASSERTS ) assert x.balance() == 1;
-+      if ( x.pred() ) {
-+       y.succ( true );
-+       x.pred( false );
-+      }
-+      else y.right = x.left;
-+      x.left = y;
-+      y.balance( 0 );
-+      x.balance( 0 );
-+     }
-+    }
-+   }
-+   else {
-+    dir = q != null && q.left != y;
-+    y.decBalance();
-+    if ( y.balance() == -1 ) break;
-+    else if ( y.balance() == -2 ) {
-+     Entry <V> x = y.left;
-+     if ( ASSERTS ) assert x != null;
-+     if ( x.balance() == 1 ) {
-+      Entry <V> w;
-+      if ( ASSERTS ) assert x.balance() == 1;
-+      w = x.right;
-+      x.right = w.left;
-+      w.left = x;
-+      y.left = w.right;
-+      w.right = y;
-+      if ( w.balance() == -1 ) {
-+       x.balance( 0 );
-+       y.balance( 1 );
-+      }
-+      else if ( w.balance() == 0 ) {
-+       x.balance( 0 );
-+       y.balance( 0 );
-+      }
-+      else {
-+       if ( ASSERTS ) assert w.balance() == 1;
-+       x.balance( -1 );
-+       y.balance( 0 );
-+      }
-+      w.balance( 0 );
-+      if ( w.pred() ) {
-+       x.succ( w );
-+       w.pred( false );
-+      }
-+      if ( w.succ() ) {
-+       y.pred( w );
-+       w.succ( false );
-+      }
-+      if ( q != null ) {
-+       if ( dir ) q.right = w;
-+       else q.left = w;
-+      }
-+      else tree = w;
-+     }
-+     else {
-+      if ( q != null ) {
-+       if ( dir ) q.right = x;
-+       else q.left = x;
-+      }
-+      else tree = x;
-+      if ( x.balance() == 0 ) {
-+       y.left = x.right;
-+       x.right = y;
-+       x.balance( +1 );
-+       y.balance( -1 );
-+       break;
-+      }
-+      if ( ASSERTS ) assert x.balance() == -1;
-+      if ( x.succ() ) {
-+       y.pred( true );
-+       x.succ( false );
-+      }
-+      else y.left = x.right;
-+      x.right = y;
-+      y.balance( 0 );
-+      x.balance( 0 );
-+     }
-+    }
-+   }
-+  }
-+  modified = true;
-+  count--;
-+  if ( ASSERTS ) checkTree( tree );
-+  return p.value;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Integer ok, final V ov ) {
-+  final V oldValue = put( ((ok).intValue()), (ov) );
-+  return modified ? (this.defRetValue) : (oldValue);
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V remove( final Object ok ) {
-+  final V oldValue = remove( ((((Integer)(ok)).intValue())) );
-+  return modified ? (oldValue) : (this.defRetValue);
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final ValueIterator i = new ValueIterator();
-+  V ev;
-+  int j = count;
-+  while( j-- != 0 ) {
-+   ev = i.next();
-+   if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
-+  }
-+  return false;
-+ }
-+ public void clear() {
-+  count = 0;
-+  tree = null;
-+  entries = null;
-+  values = null;
-+  keys = null;
-+  firstEntry = lastEntry = null;
-+ }
-+ /** This class represent an entry in a tree map.
-+	 *
-+	 * <P>We use the only "metadata", i.e., {@link Entry#info}, to store
-+	 * information about balance, predecessor status and successor status.
-+	 *
-+	 * <P>Note that since the class is recursive, it can be
-+	 * considered equivalently a tree.
-+	 */
-+ private static final class Entry <V> implements Cloneable, Int2ObjectMap.Entry <V> {
-+  /** If the bit in this mask is true, {@link #right} points to a successor. */
-+  private final static int SUCC_MASK = 1 << 31;
-+  /** If the bit in this mask is true, {@link #left} points to a predecessor. */
-+  private final static int PRED_MASK = 1 << 30;
-+  /** The bits in this mask hold the node balance info. You can get it just by casting to byte. */
-+  private final static int BALANCE_MASK = 0xFF;
-+  /** The key of this entry. */
-+  int key;
-+  /** The value of this entry. */
-+  V value;
-+  /** The pointers to the left and right subtrees. */
-+  Entry <V> left, right;
-+  /** This integers holds different information in different bits (see {@link #SUCC_MASK}, {@link #PRED_MASK} and {@link #BALANCE_MASK}). */
-+  int info;
-+  Entry() {}
-+  /** Creates a new entry with the given key and value.
-+		 *
-+		 * @param k a key.
-+		 * @param v a value.
-+		 */
-+  Entry( final int k, final V v ) {
-+   this.key = k;
-+   this.value = v;
-+   info = SUCC_MASK | PRED_MASK;
-+  }
-+  /** Returns the left subtree. 
-+		 *
-+		 * @return the left subtree (<code>null</code> if the left
-+		 * subtree is empty).
-+		 */
-+  Entry <V> left() {
-+   return ( info & PRED_MASK ) != 0 ? null : left;
-+  }
-+  /** Returns the right subtree. 
-+		 *
-+		 * @return the right subtree (<code>null</code> if the right
-+		 * subtree is empty).
-+		 */
-+  Entry <V> right() {
-+   return ( info & SUCC_MASK ) != 0 ? null : right;
-+  }
-+  /** Checks whether the left pointer is really a predecessor.
-+		 * @return true if the left pointer is a predecessor.
-+		 */
-+  boolean pred() {
-+   return ( info & PRED_MASK ) != 0;
-+  }
-+  /** Checks whether the right pointer is really a successor.
-+		 * @return true if the right pointer is a successor.
-+		 */
-+  boolean succ() {
-+   return ( info & SUCC_MASK ) != 0;
-+  }
-+  /** Sets whether the left pointer is really a predecessor.
-+		 * @param pred if true then the left pointer will be considered a predecessor.
-+		 */
-+  void pred( final boolean pred ) {
-+   if ( pred ) info |= PRED_MASK;
-+   else info &= ~PRED_MASK;
-+  }
-+  /** Sets whether the right pointer is really a successor.
-+		 * @param succ if true then the right pointer will be considered a successor.
-+		 */
-+  void succ( final boolean succ ) {
-+   if ( succ ) info |= SUCC_MASK;
-+   else info &= ~SUCC_MASK;
-+  }
-+  /** Sets the left pointer to a predecessor.
-+		 * @param pred the predecessr.
-+		 */
-+  void pred( final Entry <V> pred ) {
-+   info |= PRED_MASK;
-+   left = pred;
-+  }
-+  /** Sets the right pointer to a successor.
-+		 * @param succ the successor.
-+		 */
-+  void succ( final Entry <V> succ ) {
-+   info |= SUCC_MASK;
-+   right = succ;
-+  }
-+  /** Sets the left pointer to the given subtree.
-+		 * @param left the new left subtree.
-+		 */
-+  void left( final Entry <V> left ) {
-+   info &= ~PRED_MASK;
-+   this.left = left;
-+  }
-+  /** Sets the right pointer to the given subtree.
-+		 * @param right the new right subtree.
-+		 */
-+  void right( final Entry <V> right ) {
-+   info &= ~SUCC_MASK;
-+   this.right = right;
-+  }
-+  /** Returns the current level of the node.
-+		 * @return the current level of this node.
-+		 */
-+  int balance() {
-+   return (byte)info;
-+  }
-+  /** Sets the level of this node.
-+		 * @param level the new level of this node.
-+		 */
-+  void balance( int level ) {
-+   info &= ~BALANCE_MASK;
-+   info |= ( level & BALANCE_MASK );
-+  }
-+  /** Increments the level of this node. */
-+  void incBalance() {
-+   info = info & ~BALANCE_MASK | ( (byte)info + 1 ) & 0xFF;
-+  }
-+  /** Decrements the level of this node. */
-+  protected void decBalance() {
-+   info = info & ~BALANCE_MASK | ( (byte)info - 1 ) & 0xFF;
-+  }
-+  /** Computes the next entry in the set order.
-+		 *
-+		 * @return the next entry (<code>null</code>) if this is the last entry).
-+		 */
-+  Entry <V> next() {
-+   Entry <V> next = this.right;
-+   if ( ( info & SUCC_MASK ) == 0 ) while ( ( next.info & PRED_MASK ) == 0 ) next = next.left;
-+   return next;
-+  }
-+  /** Computes the previous entry in the set order.
-+		 *
-+		 * @return the previous entry (<code>null</code>) if this is the first entry).
-+		 */
-+  Entry <V> prev() {
-+   Entry <V> prev = this.left;
-+   if ( ( info & PRED_MASK ) == 0 ) while ( ( prev.info & SUCC_MASK ) == 0 ) prev = prev.right;
-+   return prev;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key));
-+  }
-+  public int getIntKey() {
-+   return key;
-+  }
-+  public V getValue() {
-+   return (value);
-+  }
-+  public V setValue(final V value) {
-+   final V oldValue = this.value;
-+   this.value = value;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public Entry <V> clone() {
-+   Entry <V> c;
-+   try {
-+    c = (Entry <V>)super.clone();
-+   }
-+   catch(CloneNotSupportedException cantHappen) {
-+    throw new InternalError();
-+   }
-+   c.key = key;
-+   c.value = value;
-+   c.info = info;
-+   return c;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   return ( (key) == (((e.getKey()).intValue())) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
-+  }
-+  public String toString() {
-+   return key + "=>" + value;
-+  }
-+  /*
-+		public void prettyPrint() {
-+			prettyPrint(0);
-+		}
-+
-+		public void prettyPrint(int level) {
-+			if ( pred() ) {
-+				for (int i = 0; i < level; i++)
-+					System.err.print("  ");
-+				System.err.println("pred: " + left );
-+			}
-+			else if (left != null)
-+				left.prettyPrint(level +1 );
-+			for (int i = 0; i < level; i++)
-+				System.err.print("  ");
-+			System.err.println(key + "=" + value + " (" + balance() + ")");
-+			if ( succ() ) {
-+				for (int i = 0; i < level; i++)
-+					System.err.print("  ");
-+				System.err.println("succ: " + right );
-+			}
-+			else if (right != null)
-+				right.prettyPrint(level + 1);
-+		}
-+		*/
-+ }
-+ /*
-+	public void prettyPrint() {
-+		System.err.println("size: " + count);
-+		if (tree != null) tree.prettyPrint();
-+	}
-+	*/
-+
-+ public boolean containsKey( final int k ) {
-+  return findKey( k ) != null;
-+ }
-+ public int size() {
-+  return count;
-+ }
-+ public boolean isEmpty() {
-+  return count == 0;
-+ }
-+
-+ public V get( final int k ) {
-+  final Entry <V> e = findKey( k );
-+  return e == null ? defRetValue : e.value;
-+ }
-+ public int firstIntKey() {
-+  if ( tree == null ) throw new NoSuchElementException();
-+  return firstEntry.key;
-+ }
-+ public int lastIntKey() {
-+  if ( tree == null ) throw new NoSuchElementException();
-+  return lastEntry.key;
-+ }
-+ /** An abstract iterator on the whole range.
-+	 *
-+	 * <P>This class can iterate in both directions on a threaded tree.
-+	 */
-+ private class TreeIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  Entry <V> prev;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  Entry <V> next;
-+  /** The last entry that was returned (or <code>null</code> if we did not iterate or used {@link #remove()}). */
-+  Entry <V> curr;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this {@link TreeIterator} has been created using the nonempty constructor.*/
-+  int index = 0;
-+  TreeIterator() {
-+   next = firstEntry;
-+  }
-+  TreeIterator( final int k ) {
-+   if ( ( next = locateKey( k ) ) != null ) {
-+    if ( compare( next.key, k ) <= 0 ) {
-+     prev = next;
-+     next = next.next();
-+    }
-+    else prev = next.prev();
-+   }
-+  }
-+  public boolean hasNext() { return next != null; }
-+  public boolean hasPrevious() { return prev != null; }
-+  void updateNext() {
-+   next = next.next();
-+  }
-+  Entry <V> nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = prev = next;
-+   index++;
-+   updateNext();
-+   return curr;
-+  }
-+  void updatePrevious() {
-+   prev = prev.prev();
-+  }
-+  Entry <V> previousEntry() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = next = prev;
-+   index--;
-+   updatePrevious();
-+   return curr;
-+  }
-+  public int nextIndex() {
-+   return index;
-+  }
-+  public int previousIndex() {
-+   return index - 1;
-+  }
-+  public void remove() {
-+   if ( curr == null ) throw new IllegalStateException();
-+   /* If the last operation was a next(), we are removing an entry that preceeds
-+			   the current index, and thus we must decrement it. */
-+   if ( curr == prev ) index--;
-+   next = prev = curr;
-+   updatePrevious();
-+   updateNext();
-+   Int2ObjectAVLTreeMap.this.remove( curr.key );
-+   curr = null;
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+  public int back( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasPrevious() ) previousEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ /** An iterator on the whole range.
-+	 *
-+	 * <P>This class can iterate in both directions on a threaded tree.
-+	 */
-+ private class EntryIterator extends TreeIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+  EntryIterator() {}
-+  EntryIterator( final int k ) {
-+   super( k );
-+  }
-+  public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
-+  public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
-+  public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
-+  if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
-+    final Comparator<? super Int2ObjectMap.Entry <V> > comparator = new Comparator<Int2ObjectMap.Entry <V> > () {
-+     public int compare( final Int2ObjectMap.Entry <V> x, final Int2ObjectMap.Entry <V> y ) {
-+      return Int2ObjectAVLTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() );
-+     }
-+    };
-+    public Comparator<? super Int2ObjectMap.Entry <V> > comparator() {
-+     return comparator;
-+    }
-+    public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
-+     return new EntryIterator();
-+    }
-+    public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
-+     return new EntryIterator( from.getIntKey() );
-+    }
-+    @SuppressWarnings("unchecked")
-+    public boolean contains( final Object o ) {
-+     if (!(o instanceof Map.Entry)) return false;
-+     final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
-+     if ( e.getKey() == null ) return false;
-+     final Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+     return e.equals( f );
-+    }
-+    @SuppressWarnings("unchecked")
-+    public boolean remove( final Object o ) {
-+     if (!(o instanceof Map.Entry)) return false;
-+     final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
-+     if ( e.getKey() == null ) return false;
-+     final Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+     if ( f != null ) Int2ObjectAVLTreeMap.this.remove( f.key );
-+     return f != null;
-+    }
-+    public int size() { return count; }
-+    public void clear() { Int2ObjectAVLTreeMap.this.clear(); }
-+    public Int2ObjectMap.Entry <V> first() { return firstEntry; }
-+    public Int2ObjectMap.Entry <V> last() { return lastEntry; }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
-+   };
-+  return entries;
-+ }
-+ /** An iterator on the whole range of keys.
-+	 *
-+	 * <P>This class can iterate in both directions on the keys of a threaded tree. We 
-+	 * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
-+	 * their type-specific counterparts) so that they return keys instead of entries.
-+	 */
-+ private final class KeyIterator extends TreeIterator implements IntListIterator {
-+  public KeyIterator() {}
-+  public KeyIterator( final int k ) { super( k ); }
-+  public int nextInt() { return nextEntry().key; }
-+  public int previousInt() { return previousEntry().key; }
-+  public void set( int k ) { throw new UnsupportedOperationException(); }
-+  public void add( int k ) { throw new UnsupportedOperationException(); }
-+  public Integer next() { return (Integer.valueOf(nextEntry().key)); }
-+  public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
-+  public void set( Integer ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Integer ok ) { throw new UnsupportedOperationException(); }
-+ };
-+ /** A keyset implementation using a more direct implementation for iterators. */
-+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
-+  public IntBidirectionalIterator iterator() { return new KeyIterator(); }
-+  public IntBidirectionalIterator iterator( final int from ) { return new KeyIterator( from ); }
-+ }
-+ /** Returns a type-specific sorted set view of the keys contained in this map.
-+	 *
-+	 * <P>In addition to the semantics of {@link java.util.Map#keySet()}, you can
-+	 * safely cast the set returned by this call to a type-specific sorted
-+	 * set interface.
-+	 *
-+	 * @return a type-specific sorted set view of the keys contained in this map.
-+	 */
-+ public IntSortedSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on the whole range of values.
-+	 *
-+	 * <P>This class can iterate in both directions on the values of a threaded tree. We 
-+	 * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
-+	 * their type-specific counterparts) so that they return values instead of entries.
-+	 */
-+ private final class ValueIterator extends TreeIterator implements ObjectListIterator <V> {
-+  public V next() { return nextEntry().value; }
-+  public V previous() { return previousEntry().value; }
-+  public void set( V v ) { throw new UnsupportedOperationException(); }
-+  public void add( V v ) { throw new UnsupportedOperationException(); }
-+ };
-+ /** Returns a type-specific collection view of the values contained in this map.
-+	 *
-+	 * <P>In addition to the semantics of {@link java.util.Map#values()}, you can
-+	 * safely cast the collection returned by this call to a type-specific collection
-+	 * interface.
-+	 *
-+	 * @return a type-specific collection view of the values contained in this map.
-+	 */
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public boolean contains( final Object k ) {
-+     return containsValue( k );
-+    }
-+    public int size() {
-+     return count;
-+    }
-+    public void clear() {
-+     Int2ObjectAVLTreeMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ public IntComparator comparator() {
-+  return actualComparator;
-+ }
-+ public Int2ObjectSortedMap <V> headMap( int to ) {
-+  return new Submap( (0), true, to, false );
-+ }
-+ public Int2ObjectSortedMap <V> tailMap( int from ) {
-+  return new Submap( from, false, (0), true );
-+ }
-+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
-+  return new Submap( from, false, to, false );
-+ }
-+ /** A submap with given range.
-+	 *
-+	 * <P>This class represents a submap. One has to specify the left/right
-+	 * limits (which can be set to -&infin; or &infin;). Since the submap is a
-+	 * view on the map, at a given moment it could happen that the limits of
-+	 * the range are not any longer in the main map. Thus, things such as
-+	 * {@link java.util.SortedMap#firstKey()} or {@link java.util.Collection#size()} must be always computed
-+	 * on-the-fly.  
-+	 */
-+ private final class Submap extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable {
-+     private static final long serialVersionUID = -7046029254386353129L;
-+  /** The start of the submap range, unless {@link #bottom} is true. */
-+  int from;
-+  /** The end of the submap range, unless {@link #top} is true. */
-+  int to;
-+  /** If true, the submap range starts from -&infin;. */
-+  boolean bottom;
-+  /** If true, the submap range goes to &infin;. */
-+  boolean top;
-+  /** Cached set of entries. */
-+  @SuppressWarnings("hiding")
-+  protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
-+  /** Cached set of keys. */
-+  @SuppressWarnings("hiding")
-+  protected transient IntSortedSet keys;
-+  /** Cached collection of values. */
-+  @SuppressWarnings("hiding")
-+  protected transient ObjectCollection <V> values;
-+  /** Creates a new submap with given key range.
-+		 *
-+		 * @param from the start of the submap range.
-+		 * @param bottom if true, the first parameter is ignored and the range starts from -&infin;.
-+		 * @param to the end of the submap range.
-+		 * @param top if true, the third parameter is ignored and the range goes to &infin;.
-+		 */
-+  public Submap( final int from, final boolean bottom, final int to, final boolean top ) {
-+   if ( ! bottom && ! top && Int2ObjectAVLTreeMap.this.compare( from, to ) > 0 ) throw new IllegalArgumentException( "Start key (" + from + ") is larger than end key (" + to + ")" );
-+   this.from = from;
-+   this.bottom = bottom;
-+   this.to = to;
-+   this.top = top;
-+   this.defRetValue = Int2ObjectAVLTreeMap.this.defRetValue;
-+  }
-+  public void clear() {
-+   final SubmapIterator i = new SubmapIterator();
-+   while( i.hasNext() ) {
-+    i.nextEntry();
-+    i.remove();
-+   }
-+  }
-+  /** Checks whether a key is in the submap range.
-+		 * @param k a key.
-+		 * @return true if is the key is in the submap range.
-+		 */
-+  final boolean in( final int k ) {
-+   return ( bottom || Int2ObjectAVLTreeMap.this.compare( k, from ) >= 0 ) &&
-+    ( top || Int2ObjectAVLTreeMap.this.compare( k, to ) < 0 );
-+  }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
-+   if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
-+     public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
-+      return new SubmapEntryIterator();
-+     }
-+     public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
-+      return new SubmapEntryIterator( from.getIntKey() );
-+     }
-+     public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return Int2ObjectAVLTreeMap.this.entrySet().comparator(); }
-+     @SuppressWarnings("unchecked")
-+     public boolean contains( final Object o ) {
-+      if (!(o instanceof Map.Entry)) return false;
-+      final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
-+      final Int2ObjectAVLTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+      return f != null && in( f.key ) && e.equals( f );
-+     }
-+     @SuppressWarnings("unchecked")
-+     public boolean remove( final Object o ) {
-+      if (!(o instanceof Map.Entry)) return false;
-+      final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
-+      final Int2ObjectAVLTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+      if ( f != null && in( f.key ) ) Submap.this.remove( f.key );
-+      return f != null;
-+     }
-+     public int size() {
-+      int c = 0;
-+      for( Iterator<?> i = iterator(); i.hasNext(); i.next() ) c++;
-+      return c;
-+     }
-+     public boolean isEmpty() {
-+      return ! new SubmapIterator().hasNext();
-+     }
-+     public void clear() {
-+      Submap.this.clear();
-+     }
-+     public Int2ObjectMap.Entry <V> first() { return firstEntry(); }
-+     public Int2ObjectMap.Entry <V> last() { return lastEntry(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
-+    };
-+   return entries;
-+  }
-+  private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
-+   public IntBidirectionalIterator iterator() { return new SubmapKeyIterator(); }
-+   public IntBidirectionalIterator iterator( final int from ) { return new SubmapKeyIterator( from ); }
-+  }
-+  public IntSortedSet keySet() {
-+   if ( keys == null ) keys = new KeySet();
-+   return keys;
-+  }
-+  public ObjectCollection <V> values() {
-+   if ( values == null ) values = new AbstractObjectCollection <V>() {
-+     public ObjectIterator <V> iterator() {
-+      return new SubmapValueIterator();
-+     }
-+     public boolean contains( final Object k ) {
-+      return containsValue( k );
-+     }
-+     public int size() {
-+      return Submap.this.size();
-+     }
-+     public void clear() {
-+      Submap.this.clear();
-+     }
-+    };
-+   return values;
-+  }
-+ 
-+  public boolean containsKey( final int k ) {
-+   return in( k ) && Int2ObjectAVLTreeMap.this.containsKey( k );
-+  }
-+  public boolean containsValue( final Object v ) {
-+   final SubmapIterator i = new SubmapIterator();
-+   Object ev;
-+   while( i.hasNext() ) {
-+    ev = i.nextEntry().value;
-+    if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
-+   }
-+   return false;
-+  }
-+ 
-+  public V get(final int k) {
-+   final Int2ObjectAVLTreeMap.Entry <V> e;
-+   final int kk = k;
-+   return in( kk ) && ( e = findKey( kk ) ) != null ? e.value : this.defRetValue;
-+  }
-+  public V put(final int k, final V v) {
-+   modified = false;
-+   if ( ! in( k ) ) throw new IllegalArgumentException( "Key (" + k + ") out of range [" + ( bottom ? "-" : String.valueOf( from ) ) + ", " + ( top ? "-" : String.valueOf( to ) ) + ")" );
-+   final V oldValue = Int2ObjectAVLTreeMap.this.put( k, v );
-+   return modified ? this.defRetValue : oldValue;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead.  */
-+  @Deprecated
-+  @Override
-+  public V put( final Integer ok, final V ov ) {
-+   final V oldValue = put( ((ok).intValue()), (ov) );
-+   return modified ? (this.defRetValue) : (oldValue);
-+  }
-+ 
-+  public V remove( final int k ) {
-+   modified = false;
-+   if ( ! in( k ) ) return this.defRetValue;
-+   final V oldValue = Int2ObjectAVLTreeMap.this.remove( k );
-+   return modified ? oldValue : this.defRetValue;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead.  */
-+  @Deprecated
-+  @Override
-+  public V remove( final Object ok ) {
-+   final V oldValue = remove( ((((Integer)(ok)).intValue())) );
-+   return modified ? (oldValue) : (this.defRetValue);
-+  }
-+  public int size() {
-+   final SubmapIterator i = new SubmapIterator();
-+   int n = 0;
-+   while( i.hasNext() ) {
-+    n++;
-+    i.nextEntry();
-+   }
-+   return n;
-+  }
-+  public boolean isEmpty() {
-+   return ! new SubmapIterator().hasNext();
-+  }
-+  public IntComparator comparator() {
-+   return actualComparator;
-+  }
-+  public Int2ObjectSortedMap <V> headMap( final int to ) {
-+   if ( top ) return new Submap( from, bottom, to, false );
-+   return compare( to, this.to ) < 0 ? new Submap( from, bottom, to, false ) : this;
-+  }
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) {
-+   if ( bottom ) return new Submap( from, false, to, top );
-+   return compare( from, this.from ) > 0 ? new Submap( from, false, to, top ) : this;
-+  }
-+  public Int2ObjectSortedMap <V> subMap( int from, int to ) {
-+   if ( top && bottom ) return new Submap( from, false, to, false );
-+   if ( ! top ) to = compare( to, this.to ) < 0 ? to : this.to;
-+   if ( ! bottom ) from = compare( from, this.from ) > 0 ? from : this.from;
-+    if ( ! top && ! bottom && from == this.from && to == this.to ) return this;
-+   return new Submap( from, false, to, false );
-+  }
-+  /** Locates the first entry.
-+		 *
-+		 * @return the first entry of this submap, or <code>null</code> if the submap is empty.
-+		 */
-+  public Int2ObjectAVLTreeMap.Entry <V> firstEntry() {
-+   if ( tree == null ) return null;
-+   // If this submap goes to -infinity, we return the main map first entry; otherwise, we locate the start of the map.
-+   Int2ObjectAVLTreeMap.Entry <V> e;
-+   if ( bottom ) e = firstEntry;
-+   else {
-+    e = locateKey( from );
-+    // If we find either the start or something greater we're OK.
-+    if ( compare( e.key, from ) < 0 ) e = e.next();
-+   }
-+   // Finally, if this subset doesn't go to infinity, we check that the resulting key isn't greater than the end.
-+   if ( e == null || ! top && compare( e.key, to ) >= 0 ) return null;
-+   return e;
-+  }
-+  /** Locates the last entry.
-+		 *
-+		 * @return the last entry of this submap, or <code>null</code> if the submap is empty.
-+		 */
-+  public Int2ObjectAVLTreeMap.Entry <V> lastEntry() {
-+   if ( tree == null ) return null;
-+   // If this submap goes to infinity, we return the main map last entry; otherwise, we locate the end of the map.
-+   Int2ObjectAVLTreeMap.Entry <V> e;
-+   if ( top ) e = lastEntry;
-+   else {
-+    e = locateKey( to );
-+    // If we find something smaller than the end we're OK.
-+    if ( compare( e.key, to ) >= 0 ) e = e.prev();
-+   }
-+   // Finally, if this subset doesn't go to -infinity, we check that the resulting key isn't smaller than the start.
-+   if ( e == null || ! bottom && compare( e.key, from ) < 0 ) return null;
-+   return e;
-+  }
-+  public int firstIntKey() {
-+   Int2ObjectAVLTreeMap.Entry <V> e = firstEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.key;
-+  }
-+  public int lastIntKey() {
-+   Int2ObjectAVLTreeMap.Entry <V> e = lastEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.key;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead.  */
-+  @Deprecated
-+  @Override
-+  public Integer firstKey() {
-+   Int2ObjectAVLTreeMap.Entry <V> e = firstEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.getKey();
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead.  */
-+  @Deprecated
-+  @Override
-+  public Integer lastKey() {
-+   Int2ObjectAVLTreeMap.Entry <V> e = lastEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.getKey();
-+  }
-+  /** An iterator for subranges.
-+		 * 
-+		 * <P>This class inherits from {@link TreeIterator}, but overrides the methods that
-+		 * update the pointer after a {@link java.util.ListIterator#next()} or {@link java.util.ListIterator#previous()}. If we would
-+		 * move out of the range of the submap we just overwrite the next or previous
-+		 * entry with <code>null</code>.
-+		 */
-+  private class SubmapIterator extends TreeIterator {
-+   SubmapIterator() {
-+    next = firstEntry();
-+   }
-+   SubmapIterator( final int k ) {
-+    this();
-+    if ( next != null ) {
-+     if ( ! bottom && compare( k, next.key ) < 0 ) prev = null;
-+     else if ( ! top && compare( k, ( prev = lastEntry() ).key ) >= 0 ) next = null;
-+     else {
-+      next = locateKey( k );
-+      if ( compare( next.key, k ) <= 0 ) {
-+       prev = next;
-+       next = next.next();
-+      }
-+      else prev = next.prev();
-+     }
-+    }
-+   }
-+   void updatePrevious() {
-+    prev = prev.prev();
-+    if ( ! bottom && prev != null && Int2ObjectAVLTreeMap.this.compare( prev.key, from ) < 0 ) prev = null;
-+   }
-+   void updateNext() {
-+    next = next.next();
-+    if ( ! top && next != null && Int2ObjectAVLTreeMap.this.compare( next.key, to ) >= 0 ) next = null;
-+   }
-+  }
-+  private class SubmapEntryIterator extends SubmapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+   SubmapEntryIterator() {}
-+   SubmapEntryIterator( final int k ) {
-+    super( k );
-+   }
-+   public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
-+   public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
-+   public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+   public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  }
-+  /** An iterator on a subrange of keys.
-+		 *
-+		 * <P>This class can iterate in both directions on a subrange of the
-+		 * keys of a threaded tree. We simply override the {@link
-+		 * java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
-+		 * type-specific counterparts) so that they return keys instead of
-+		 * entries.
-+		 */
-+  private final class SubmapKeyIterator extends SubmapIterator implements IntListIterator {
-+   public SubmapKeyIterator() { super(); }
-+   public SubmapKeyIterator( int from ) { super( from ); }
-+   public int nextInt() { return nextEntry().key; }
-+   public int previousInt() { return previousEntry().key; }
-+   public void set( int k ) { throw new UnsupportedOperationException(); }
-+   public void add( int k ) { throw new UnsupportedOperationException(); }
-+   public Integer next() { return (Integer.valueOf(nextEntry().key)); }
-+   public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
-+   public void set( Integer ok ) { throw new UnsupportedOperationException(); }
-+   public void add( Integer ok ) { throw new UnsupportedOperationException(); }
-+  };
-+  /** An iterator on a subrange of values.
-+		 *
-+		 * <P>This class can iterate in both directions on the values of a
-+		 * subrange of the keys of a threaded tree. We simply override the
-+		 * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
-+		 * type-specific counterparts) so that they return values instead of
-+		 * entries.  
-+		 */
-+  private final class SubmapValueIterator extends SubmapIterator implements ObjectListIterator <V> {
-+   public V next() { return nextEntry().value; }
-+   public V previous() { return previousEntry().value; }
-+   public void set( V v ) { throw new UnsupportedOperationException(); }
-+   public void add( V v ) { throw new UnsupportedOperationException(); }
-+  };
-+ }
-+ /** Returns a deep copy of this tree map.
-+	 *
-+	 * <P>This method performs a deep copy of this tree map; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 * @return a deep copy of this tree map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectAVLTreeMap <V> clone() {
-+  Int2ObjectAVLTreeMap <V> c;
-+  try {
-+   c = (Int2ObjectAVLTreeMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.allocatePaths();
-+  if ( count != 0 ) {
-+   // Also this apparently unfathomable code is derived from GNU libavl.
-+   Entry <V> e, p, q, rp = new Entry <V>(), rq = new Entry <V>();
-+   p = rp;
-+   rp.left( tree );
-+   q = rq;
-+   rq.pred( null );
-+   while( true ) {
-+    if ( ! p.pred() ) {
-+     e = p.left.clone();
-+     e.pred( q.left );
-+     e.succ( q );
-+     q.left( e );
-+     p = p.left;
-+     q = q.left;
-+    }
-+    else {
-+     while( p.succ() ) {
-+      p = p.right;
-+      if ( p == null ) {
-+       q.right = null;
-+       c.tree = rq.left;
-+       c.firstEntry = c.tree;
-+       while( c.firstEntry.left != null ) c.firstEntry = c.firstEntry.left;
-+       c.lastEntry = c.tree;
-+       while( c.lastEntry.right != null ) c.lastEntry = c.lastEntry.right;
-+       return c;
-+      }
-+      q = q.right;
-+     }
-+     p = p.right;
-+     q = q.right;
-+    }
-+    if ( ! p.succ() ) {
-+     e = p.right.clone();
-+     e.succ( q.right );
-+     e.pred( q );
-+     q.right( e );
-+    }
-+   }
-+  }
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  int n = count;
-+  EntryIterator i = new EntryIterator();
-+  Entry <V> e;
-+  s.defaultWriteObject();
-+  while(n-- != 0) {
-+   e = i.nextEntry();
-+   s.writeInt( e.key );
-+   s.writeObject( e.value );
-+  }
-+ }
-+ /** Reads the given number of entries from the input stream, returning the corresponding tree. 
-+	 *
-+	 * @param s the input stream.
-+	 * @param n the (positive) number of entries to read.
-+	 * @param pred the entry containing the key that preceeds the first key in the tree.
-+	 * @param succ the entry containing the key that follows the last key in the tree.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ private Entry <V> readTree( final java.io.ObjectInputStream s, final int n, final Entry <V> pred, final Entry <V> succ ) throws java.io.IOException, ClassNotFoundException {
-+  if ( n == 1 ) {
-+   final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
-+   top.pred( pred );
-+   top.succ( succ );
-+   return top;
-+  }
-+  if ( n == 2 ) {
-+   /* We handle separately this case so that recursion will
-+			 *always* be on nonempty subtrees. */
-+   final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
-+   top.right( new Entry <V>( s.readInt(), (V) s.readObject() ) );
-+   top.right.pred( top );
-+   top.balance( 1 );
-+   top.pred( pred );
-+   top.right.succ( succ );
-+   return top;
-+  }
-+  // The right subtree is the largest one.
-+  final int rightN = n / 2, leftN = n - rightN - 1;
-+  final Entry <V> top = new Entry <V>();
-+  top.left( readTree( s, leftN, pred, top ) );
-+  top.key = s.readInt();
-+  top.value = (V) s.readObject();
-+  top.right( readTree( s, rightN, top, succ ) );
-+  if ( n == ( n & -n ) ) top.balance( 1 ); // Quick test for determining whether n is a power of 2.
-+  return top;
-+ }
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  /* The storedComparator is now correctly set, but we must restore
-+		   on-the-fly the actualComparator. */
-+  setActualComparator();
-+  allocatePaths();
-+  if ( count != 0 ) {
-+   tree = readTree( s, count, null, null );
-+   Entry <V> e;
-+   e = tree;
-+   while( e.left() != null ) e = e.left();
-+   firstEntry = e;
-+   e = tree;
-+   while( e.right() != null ) e = e.right();
-+   lastEntry = e;
-+  }
-+  if ( ASSERTS ) checkTree( tree );
-+ }
-+ private static <V> int checkTree( @SuppressWarnings("unused") Entry <V> e ) { return 0; }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2007-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Map;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectCollections;
-+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
-+import it.unimi.dsi.fastutil.objects.ObjectArrays;
-+/** A simple, brute-force implementation of a map based on two parallel backing arrays. 
-+ * 
-+ * <p>The main purpose of this
-+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very 
-+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
-+ */
-+public class Int2ObjectArrayMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable {
-+ private static final long serialVersionUID = 1L;
-+ /** The keys (valid up to {@link #size}, excluded). */
-+ private transient int[] key;
-+ /** The values (parallel to {@link #key}). */
-+ private transient Object[] value;
-+ /** The number of valid entries in {@link #key} and {@link #value}. */
-+ private int size;
-+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
-+	 * 
-+	 * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
-+	 * 
-+	 * @param key the key array.
-+	 * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
-+	 */
-+ public Int2ObjectArrayMap( final int[] key, final Object[] value ) {
-+  this.key = key;
-+  this.value = value;
-+  size = key.length;
-+  if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
-+ }
-+ /** Creates a new empty array map.
-+	 */
-+ public Int2ObjectArrayMap() {
-+  this.key = IntArrays.EMPTY_ARRAY;
-+  this.value = ObjectArrays.EMPTY_ARRAY;
-+ }
-+ /** Creates a new empty array map of given capacity.
-+	 *
-+	 * @param capacity the initial capacity.
-+	 */
-+ public Int2ObjectArrayMap( final int capacity ) {
-+  this.key = new int[ capacity ];
-+  this.value = new Object[ capacity ];
-+ }
-+ /** Creates a new empty array map copying the entries of a given map.
-+	 *
-+	 * @param m a map.
-+	 */
-+ public Int2ObjectArrayMap( final Int2ObjectMap <V> m ) {
-+  this( m.size() );
-+  putAll( m );
-+ }
-+ /** Creates a new empty array map copying the entries of a given map.
-+	 *
-+	 * @param m a map.
-+	 */
-+ public Int2ObjectArrayMap( final Map<? extends Integer, ? extends V> m ) {
-+  this( m.size() );
-+  putAll( m );
-+ }
-+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
-+	 * 
-+	 * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
-+	 * 
-+	 * @param key the key array.
-+	 * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
-+	 * @param size the number of valid elements in <code>key</code> and <code>value</code>.
-+	 */
-+ public Int2ObjectArrayMap( final int[] key, final Object[] value, final int size ) {
-+  this.key = key;
-+  this.value = value;
-+  this.size = size;
-+  if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
-+  if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
-+ }
-+ private final class EntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  @Override
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
-+   return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
-+    int curr = -1, next = 0;
-+    public boolean hasNext() {
-+     return next < size;
-+    }
-+    @SuppressWarnings("unchecked")
-+    public Entry <V> next() {
-+     if ( ! hasNext() ) throw new NoSuchElementException();
-+     return new AbstractInt2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
-+    }
-+    public void remove() {
-+     if ( curr == -1 ) throw new IllegalStateException();
-+     curr = -1;
-+     final int tail = size-- - next--;
-+     System.arraycopy( key, next + 1, key, next, tail );
-+     System.arraycopy( value, next + 1, value, next, tail );
-+     value[ size ] = null;
-+    }
-+   };
-+  }
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
-+   return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
-+    int next = 0, curr = -1;
-+    final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
-+    public boolean hasNext() {
-+     return next < size;
-+    }
-+    @SuppressWarnings("unchecked")
-+    public Entry <V> next() {
-+     if ( ! hasNext() ) throw new NoSuchElementException();
-+     entry.key = key[ curr = next ];
-+     entry.value = (V) value[ next++ ];
-+     return entry;
-+    }
-+    public void remove() {
-+     if ( curr == -1 ) throw new IllegalStateException();
-+     curr = -1;
-+     final int tail = size-- - next--;
-+     System.arraycopy( key, next + 1, key, next, tail );
-+     System.arraycopy( value, next + 1, value, next, tail );
-+     value[ size ] = null;
-+    }
-+   };
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( Object o ) {
-+   if ( ! ( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   return Int2ObjectArrayMap.this.containsKey( k ) && ( (Int2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Int2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
-+  }
-+  @SuppressWarnings("unchecked")
-+  @Override
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   final V v = (e.getValue());
-+   final int oldPos = Int2ObjectArrayMap.this.findKey( k );
-+   if ( oldPos == -1 || ! ( (v) == null ? (Int2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Int2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
-+   final int tail = size - oldPos - 1;
-+   System.arraycopy( Int2ObjectArrayMap.this.key, oldPos + 1, Int2ObjectArrayMap.this.key, oldPos, tail );
-+   System.arraycopy( Int2ObjectArrayMap.this.value, oldPos + 1, Int2ObjectArrayMap.this.value, oldPos, tail );
-+   Int2ObjectArrayMap.this.size--;
-+   Int2ObjectArrayMap.this.value[ size ] = null;
-+   return true;
-+  }
-+ }
-+ public FastEntrySet <V> int2ObjectEntrySet() {
-+  return new EntrySet();
-+ }
-+ private int findKey( final int k ) {
-+  final int[] key = this.key;
-+  for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
-+  return -1;
-+ }
-+ @SuppressWarnings("unchecked")
-+ public V get( final int k ) {
-+  final int[] key = this.key;
-+  for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
-+  return defRetValue;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ @Override
-+ public void clear() {
-+  for( int i = size; i-- != 0; ) {
-+   value[ i ] = null;
-+  }
-+  size = 0;
-+ }
-+ @Override
-+ public boolean containsKey( final int k ) {
-+  return findKey( k ) != -1;
-+ }
-+ @Override
-+ public boolean containsValue( Object v ) {
-+  for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ @Override
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ @Override
-+ @SuppressWarnings("unchecked")
-+ public V put( int k, V v ) {
-+  final int oldKey = findKey( k );
-+  if ( oldKey != -1 ) {
-+   final V oldValue = (V) value[ oldKey ];
-+   value[ oldKey ] = v;
-+   return oldValue;
-+  }
-+  if ( size == key.length ) {
-+   final int[] newKey = new int[ size == 0 ? 2 : size * 2 ];
-+   final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
-+   for( int i = size; i-- != 0; ) {
-+    newKey[ i ] = key[ i ];
-+    newValue[ i ] = value[ i ];
-+   }
-+   key = newKey;
-+   value = newValue;
-+  }
-+  key[ size ] = k;
-+  value[ size ] = v;
-+  size++;
-+  return defRetValue;
-+ }
-+ @Override
-+ @SuppressWarnings("unchecked")
-+ public V remove( final int k ) {
-+  final int oldPos = findKey( k );
-+  if ( oldPos == -1 ) return defRetValue;
-+  final V oldValue = (V) value[ oldPos ];
-+  final int tail = size - oldPos - 1;
-+  System.arraycopy( key, oldPos + 1, key, oldPos, tail );
-+  System.arraycopy( value, oldPos + 1, value, oldPos, tail );
-+  size--;
-+  value[ size ] = null;
-+  return oldValue;
-+ }
-+ @Override
-+ public IntSet keySet() {
-+  return new IntArraySet ( key, size );
-+ }
-+ @Override
-+ public ObjectCollection <V> values() {
-+  return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectArrayMap <V> clone() {
-+  Int2ObjectArrayMap <V> c;
-+  try {
-+   c = (Int2ObjectArrayMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) {
-+   s.writeInt( key[ i ] );
-+   s.writeObject( value[ i ] );
-+  }
-+ }
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  key = new int[ size ];
-+  value = new Object[ size ];
-+  for( int i = 0; i < size; i++ ) {
-+   key[ i ] = s.readInt();
-+   value[ i ] = s.readObject();
-+  }
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Function;
-+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
-+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
-+ * a key.  Rather, they return a {@linkplain #defaultReturnValue() default
-+ * return value}, which is set to 0 cast to the return type (<code>false</code>
-+ * for booleans) at creation, but can be changed using the
-+ * <code>defaultReturnValue()</code> method. 
-+ *
-+ * <P>For uniformity reasons, even maps returning objects implement the default
-+ * return value (of course, in this case the default return value is
-+ * initialized to <code>null</code>).
-+ *
-+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
-+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
-+ * that standard versions of <code>get()</code>, <code>put()</code> and
-+ * <code>remove()</code> for maps with primitive-type values <em>return
-+ * <code>null</code> to denote missing keys</em> rather than wrap the default
-+ * return value in an object (of course, for maps with object keys and values
-+ * this is not possible, as there is no type-specific version).
-+ *
-+ * @see Function
-+ */
-+public interface Int2ObjectFunction <V> extends Function<Integer, V> {
-+ /** Adds a pair to the map.
-+	 *
-+	 * @param key the key.
-+	 * @param value the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#put(Object,Object)
-+	 */
-+ V put( int key, V value );
-+ /** Returns the value to which the given key is mapped.
-+	 *
-+	 * @param key the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#get(Object)
-+	 */
-+ V get( int key );
-+ /** Removes the mapping with the given key.
-+	 * @param key the key.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#remove(Object)
-+	 */
-+ V remove( int key );
-+ /**
-+	 * @see Function#containsKey(Object)
-+	 */
-+ boolean containsKey( int key );
-+ /** Sets the default return value. 
-+	 *
-+	 * This value must be returned by type-specific versions of
-+	 * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
-+	 * denote that the map does not contain the specified key. It must be
-+	 * 0/<code>false</code>/<code>null</code> by default.
-+	 *
-+	 * @param rv the new default return value.
-+	 * @see #defaultReturnValue()
-+	 */
-+ void defaultReturnValue( V rv );
-+ /** Gets the default return value.
-+	 *
-+	 * @return the current default return value.
-+	 */
-+ V defaultReturnValue();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** A class providing static methods and objects that do useful things with type-specific functions.
-+ *
-+ * @see it.unimi.dsi.fastutil.Function
-+ * @see java.util.Collections
-+ */
-+public class Int2ObjectFunctions {
-+ private Int2ObjectFunctions() {}
-+ /** An immutable class representing an empty type-specific function.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific function.
-+	 */
-+ public static class EmptyFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyFunction() {}
-+  public V get( final int k ) { return (null); }
-+  public boolean containsKey( final int k ) { return false; }
-+  public V defaultReturnValue() { return (null); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final Object k ) { return null; }
-+  public int size() { return 0; }
-+  public void clear() {}
-+  private Object readResolve() { return EMPTY_FUNCTION; }
-+  public Object clone() { return EMPTY_FUNCTION; }
-+ }
-+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
-+ /** An immutable class representing a type-specific singleton function.	 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific function.
-+	 */
-+ public static class Singleton <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final int key;
-+  protected final V value;
-+  protected Singleton( final int key, final V value ) {
-+   this.key = key;
-+   this.value = value;
-+  }
-+  public boolean containsKey( final int k ) { return ( (key) == (k) ); }
-+  public V get( final int k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
-+  public int size() { return 1; }
-+  public Object clone() { return this; }
-+ }
-+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned function is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned function.
-+	 * @param value the only value of the returned function.
-+	 * @return a type-specific immutable function containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectFunction <V> singleton( final int key, V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned function is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned function.
-+	 * @param value the only value of the returned function.
-+	 * @return a type-specific immutable function containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectFunction <V> singleton( final Integer key, final V value ) {
-+  return new Singleton <V>( ((key).intValue()), (value) );
-+ }
-+ /** A synchronized wrapper class for functions. */
-+ public static class SynchronizedFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectFunction <V> function;
-+  protected final Object sync;
-+  protected SynchronizedFunction( final Int2ObjectFunction <V> f, final Object sync ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedFunction( final Int2ObjectFunction <V> f ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+   this.sync = this;
-+  }
-+  public int size() { synchronized( sync ) { return function.size(); } }
-+  public boolean containsKey( final int k ) { synchronized( sync ) { return function.containsKey( k ); } }
-+  public V defaultReturnValue() { synchronized( sync ) { return function.defaultReturnValue(); } }
-+  public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { function.defaultReturnValue( defRetValue ); } }
-+  public V put( final int k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
-+  public void clear() { synchronized( sync ) { function.clear(); } }
-+  public String toString() { synchronized( sync ) { return function.toString(); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V put( final Integer k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
-+  @Override
-+  public V get( final Object k ) { synchronized( sync ) { return function.get( k ); } }
-+  @Override
-+  public V remove( final Object k ) { synchronized( sync ) { return function.remove( k ); } }
-+  @Override
-+  public V remove( final int k ) { synchronized( sync ) { return function.remove( k ); } }
-+  @Override
-+  public V get( final int k ) { synchronized( sync ) { return function.get( k ); } }
-+  public boolean containsKey( final Object ok ) { synchronized( sync ) { return function.containsKey( ok ); } }
-+ }
-+ /** Returns a synchronized type-specific function backed by the given type-specific function.
-+	 *
-+	 * @param f the function to be wrapped in a synchronized function.
-+	 * @return a synchronized view of the specified function.
-+	 * @see java.util.Collections#synchronizedMap(java.util.Map)
-+	 */
-+ public static <V> Int2ObjectFunction <V> synchronize( final Int2ObjectFunction <V> f ) { return new SynchronizedFunction <V>( f ); }
-+ /** Returns a synchronized type-specific function backed by the given type-specific function, using an assigned object to synchronize.
-+	 *
-+	 * @param f the function to be wrapped in a synchronized function.
-+	 * @param sync an object that will be used to synchronize the access to the function.
-+	 * @return a synchronized view of the specified function.
-+	 * @see java.util.Collections#synchronizedMap(java.util.Map)
-+	 */
-+ public static <V> Int2ObjectFunction <V> synchronize( final Int2ObjectFunction <V> f, final Object sync ) { return new SynchronizedFunction <V>( f, sync ); }
-+ /** An unmodifiable wrapper class for functions. */
-+ public static class UnmodifiableFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectFunction <V> function;
-+  protected UnmodifiableFunction( final Int2ObjectFunction <V> f ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+  }
-+  public int size() { return function.size(); }
-+  public boolean containsKey( final int k ) { return function.containsKey( k ); }
-+  public V defaultReturnValue() { return function.defaultReturnValue(); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  public V put( final int k, final V v ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return function.toString(); }
-+  @Override
-+  public V remove( final int k ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final int k ) { return function.get( k ); }
-+  public boolean containsKey( final Object ok ) { return function.containsKey( ok ); }
-+  @Override
-+  public V remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final Object k ) { return function.get( k ); }
-+ }
-+ /** Returns an unmodifiable type-specific function backed by the given type-specific function.
-+	 *
-+	 * @param f the function to be wrapped in an unmodifiable function.
-+	 * @return an unmodifiable view of the specified function.
-+	 * @see java.util.Collections#unmodifiableMap(java.util.Map)
-+	 */
-+ public static <V> Int2ObjectFunction <V> unmodifiable( final Int2ObjectFunction <V> f ) { return new UnmodifiableFunction <V>( f ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Comparator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+/**  A type-specific linked hash map with with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
-+ * have been added to the map (addition of pairs whose key is already present 
-+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
-+ * order of the keys. The order is kept by means of a doubly linked list, represented
-+ * <i>via</i> an array of longs parallel to the table.
-+ *
-+ * <P>This class implements the interface of a sorted map, so to allow easy
-+ * access of the iteration order: for instance, you can get the first key
-+ * in iteration order with {@code firstKey()} without having to create an
-+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
-+ * contract because all submap methods throw an exception and {@link
-+ * #comparator()} returns always <code>null</code>.
-+ *
-+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
-+ * to use instances of this class as a cache (e.g., with LRU policy).
-+ *
-+ * <P>The iterators provided by the views of this class using are type-specific
-+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
-+ * element <em>which is a key of the map</em>, or
-+ * a {@link NoSuchElementException} exception will be thrown.
-+ * If, however, the provided element is not the first or last key in the
-+ * set, the first access to the list index will require linear time, as in the worst case
-+ * the entire key set must be scanned in iteration order to retrieve the positional
-+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
-+ * however, all operations will be performed in constant time.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Int2ObjectLinkedOpenHashMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient int[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int first = -1;
-+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int last = -1;
-+ /** For each entry, the next and the previous entry in iteration order,
-+     * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
-+     * The first entry contains predecessor -1, and the last entry 
-+     * contains successor -1. */
-+     protected transient long[] link;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastSortedEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient IntSortedSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectLinkedOpenHashMap( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new int[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+  link = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v, final float f ) {
-+  this( k.length, f );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  fixPointers( pos );
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  fixPointers( n );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Integer,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final int k, final V v) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final int k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Integer ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).intValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  int curr;
-+  final int[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+   fixPointers( pos, last );
-+  }
-+ }
-+
-+ public V remove( final int k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final int k = ((((Integer)(ok)).intValue()));
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ private V setValue( final int pos, final V v ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** Removes the mapping associated with the first key in iteration order.
-+	 * @return the value previously associated with the first key in iteration order.
-+	 * @throws NoSuchElementException is this map is empty.
-+	 */
-+ public V removeFirst() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = first;
-+  // Abbreviated version of fixPointers(pos)
-+  first = (int) link[ pos ];
-+  if ( 0 <= first ) {
-+   // Special case of SET_PREV( link[ first ], -1 )
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  size--;
-+  final V v = value[ pos ];
-+  if ( pos == n ) {
-+   containsNullKey = false;
-+   value[ n ] = null;
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return v;
-+ }
-+ /** Removes the mapping associated with the last key in iteration order.
-+	 * @return the value previously associated with the last key in iteration order.
-+	 * @throws NoSuchElementException is this map is empty.
-+	 */
-+ public V removeLast() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = last;
-+  // Abbreviated version of fixPointers(pos)
-+  last = (int) ( link[ pos ] >>> 32 );
-+  if ( 0 <= last ) {
-+   // Special case of SET_NEXT( link[ last ], -1 )
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  size--;
-+  final V v = value[ pos ];
-+  if ( pos == n ) {
-+   containsNullKey = false;
-+   value[ n ] = null;
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return v;
-+ }
-+ private void moveIndexToFirst( final int i ) {
-+  if ( size == 1 || first == i ) return;
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   // Special case of SET_NEXT( link[ last ], -1 );
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+  first = i;
-+ }
-+ private void moveIndexToLast( final int i ) {
-+  if ( size == 1 || last == i ) return;
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   // Special case of SET_PREV( link[ first ], -1 );
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+  last = i;
-+ }
-+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V getAndMoveToFirst( final int k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToFirst( n );
-+    return value[ n ];
-+   }
-+   return defRetValue;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) {
-+   moveIndexToFirst( pos );
-+   return value[ pos ];
-+  }
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) {
-+    moveIndexToFirst( pos );
-+    return value[ pos ];
-+   }
-+  }
-+ }
-+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V getAndMoveToLast( final int k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToLast( n );
-+    return value[ n ];
-+   }
-+   return defRetValue;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) {
-+   moveIndexToLast( pos );
-+   return value[ pos ];
-+  }
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) {
-+    moveIndexToLast( pos );
-+    return value[ pos ];
-+   }
-+  }
-+ }
-+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @param v the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V putAndMoveToFirst( final int k, final V v ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToFirst( n );
-+    return setValue( n, v );
-+   }
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) {
-+     moveIndexToFirst( pos );
-+     return setValue( pos, v );
-+    }
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) {
-+      moveIndexToFirst( pos );
-+      return setValue( pos, v );
-+     }
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+   first = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return defRetValue;
-+ }
-+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @param v the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V putAndMoveToLast( final int k, final V v ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToLast( n );
-+    return setValue( n, v );
-+   }
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) {
-+     moveIndexToLast( pos );
-+     return setValue( pos, v );
-+    }
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) {
-+      moveIndexToLast( pos );
-+      return setValue( pos, v );
-+     }
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return defRetValue;
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Integer ok ) {
-+  if ( ok == null ) return null;
-+  final int k = ((ok).intValue());
-+  if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final int k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final int k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final int key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+  first = last = -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key[ index ]));
-+  }
-+  public int getIntKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** Modifies the {@link #link} vector so that the given entry is removed.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param i the index of an entry. 
-+	 */
-+ protected void fixPointers( final int i ) {
-+  if ( size == 0 ) {
-+   first = last = -1;
-+   return;
-+  }
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   if (0 <= first) {
-+    // Special case of SET_PREV( link[ first ], -1 )
-+    link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+   }
-+   return;
-+  }
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   if (0 <= last) {
-+    // Special case of SET_NEXT( link[ last ], -1 )
-+    link[ last ] |= -1 & 0xFFFFFFFFL;
-+   }
-+   return;
-+  }
-+  final long linki = link[ i ];
-+  final int prev = (int) ( linki >>> 32 );
-+  final int next = (int) linki;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+ }
-+ /** Modifies the {@link #link} vector for a shift from s to d.
-+	 * <P>This method will complete in constant time.
-+	 *
-+	 * @param s the source position.
-+	 * @param d the destination position.
-+	 */
-+ protected void fixPointers( int s, int d ) {
-+  if ( size == 1 ) {
-+   first = last = d;
-+   // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
-+   link[ d ] = -1L;
-+   return;
-+  }
-+  if ( first == s ) {
-+   first = d;
-+   link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  if ( last == s ) {
-+   last = d;
-+   link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  final long links = link[ s ];
-+  final int prev = (int) ( links >>> 32 );
-+  final int next = (int) links;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ d ] = links;
-+ }
-+ /** Returns the first key of this map in iteration order.
-+	 *
-+	 * @return the first key in iteration order.
-+	 */
-+ public int firstIntKey() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ first ];
-+ }
-+ /** Returns the last key of this map in iteration order.
-+	 *
-+	 * @return the last key in iteration order.
-+	 */
-+ public int lastIntKey() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ last ];
-+ }
-+ public IntComparator comparator() { return null; }
-+ public Int2ObjectSortedMap <V> tailMap( int from ) { throw new UnsupportedOperationException(); }
-+ public Int2ObjectSortedMap <V> headMap( int to ) { throw new UnsupportedOperationException(); }
-+ public Int2ObjectSortedMap <V> subMap( int from, int to ) { throw new UnsupportedOperationException(); }
-+ /** A list iterator over a linked map.
-+	 *
-+	 * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
-+	 */
-+ private class MapIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  int prev = -1;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  int next = -1;
-+  /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
-+  int curr = -1;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
-+  int index = -1;
-+  private MapIterator() {
-+   next = first;
-+   index = 0;
-+  }
-+  private MapIterator( final int from ) {
-+   if ( ( (from) == (0) ) ) {
-+    if ( Int2ObjectLinkedOpenHashMap.this.containsNullKey ) {
-+     next = (int) link[ n ];
-+     prev = n;
-+     return;
-+    }
-+    else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
-+   }
-+   if ( ( (key[ last ]) == (from) ) ) {
-+    prev = last;
-+    index = size;
-+    return;
-+   }
-+   // The starting point.
-+   int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( (key[ pos ]) == (from) ) ) {
-+     // Note: no valid index known.
-+     next = (int) link[ pos ];
-+     prev = pos;
-+     return;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
-+  }
-+  public boolean hasNext() { return next != -1; }
-+  public boolean hasPrevious() { return prev != -1; }
-+  private final void ensureIndexKnown() {
-+   if ( index >= 0 ) return;
-+   if ( prev == -1 ) {
-+    index = 0;
-+    return;
-+   }
-+   if ( next == -1 ) {
-+    index = size;
-+    return;
-+   }
-+   int pos = first;
-+   index = 1;
-+   while( pos != prev ) {
-+    pos = (int) link[ pos ];
-+    index++;
-+   }
-+  }
-+  public int nextIndex() {
-+   ensureIndexKnown();
-+   return index;
-+  }
-+  public int previousIndex() {
-+   ensureIndexKnown();
-+   return index - 1;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = next;
-+   next = (int) link[ curr ];
-+   prev = curr;
-+   if ( index >= 0 ) index++;
-+   return curr;
-+  }
-+  public int previousEntry() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = prev;
-+   prev = (int) ( link[ curr ] >>> 32 );
-+   next = curr;
-+   if ( index >= 0 ) index--;
-+   return curr;
-+  }
-+  public void remove() {
-+   ensureIndexKnown();
-+   if ( curr == -1 ) throw new IllegalStateException();
-+   if ( curr == prev ) {
-+    /* If the last operation was a next(), we are removing an entry that preceeds
-+				   the current index, and thus we must decrement it. */
-+    index--;
-+    prev = (int) ( link[ curr ] >>> 32 );
-+   }
-+   else
-+    next = (int) link[ curr ];
-+   size--;
-+   /* Now we manually fix the pointers. Because of our knowledge of next
-+			   and prev, this is going to be faster than calling fixPointers(). */
-+   if ( prev == -1 ) first = next;
-+   else
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   if ( next == -1 ) last = prev;
-+   else
-+    link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   int last, slot, pos = curr;
-+   curr = -1;
-+   if ( pos == n ) {
-+    Int2ObjectLinkedOpenHashMap.this.containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else {
-+    int curr;
-+    final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
-+    // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.			
-+    for(;;) {
-+     pos = ( ( last = pos ) + 1 ) & mask;
-+     for(;;) {
-+      if ( ( (curr = key[ pos ]) == (0) ) ) {
-+       key[ last ] = (0);
-+       value[ last ] = null;
-+       return;
-+      }
-+      slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+      if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+      pos = ( pos + 1 ) & mask;
-+     }
-+     key[ last ] = curr;
-+     value[ last ] = value[ pos ];
-+     if ( next == pos ) next = last;
-+     if ( prev == pos ) prev = last;
-+     fixPointers( pos, last );
-+    }
-+   }
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+  public int back( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasPrevious() ) previousEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public EntryIterator() {}
-+  public EntryIterator( int from ) {
-+   super( from );
-+  }
-+  public MapEntry next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  public MapEntry previous() {
-+   return entry = new MapEntry( previousEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+  public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+  final MapEntry entry = new MapEntry();
-+  public FastEntryIterator() {}
-+  public FastEntryIterator( int from ) {
-+   super( from );
-+  }
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+  public MapEntry previous() {
-+   entry.index = previousEntry();
-+   return entry;
-+  }
-+  public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSortedSet<Int2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
-+  public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return null; }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> fromElement, Int2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
-+  public Int2ObjectMap.Entry <V> first() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return new MapEntry( Int2ObjectLinkedOpenHashMap.this.first );
-+  }
-+  public Int2ObjectMap.Entry <V> last() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return new MapEntry( Int2ObjectLinkedOpenHashMap.this.last );
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   if ( ( (k) == (0) ) ) return ( Int2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   int curr;
-+   final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   final V v = (e.getValue());
-+   if ( ( (k) == (0) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   int curr;
-+   final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (curr) == (k) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (curr) == (k) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Int2ObjectLinkedOpenHashMap.this.clear();
-+  }
-+  public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
-+   return new EntryIterator( from.getIntKey() );
-+  }
-+  public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( final Int2ObjectMap.Entry <V> from ) {
-+   return new FastEntryIterator( from.getIntKey() );
-+  }
-+ }
-+ public FastSortedEntrySet <V> int2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements IntListIterator {
-+  public KeyIterator( final int k ) { super( k ); }
-+  public int previousInt() { return key[ previousEntry() ]; }
-+  public void set( int k ) { throw new UnsupportedOperationException(); }
-+  public void add( int k ) { throw new UnsupportedOperationException(); }
-+  public Integer previous() { return (Integer.valueOf(key[ previousEntry() ])); }
-+  public void set( Integer ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Integer ok ) { throw new UnsupportedOperationException(); }
-+  public KeyIterator() { super(); }
-+  public int nextInt() { return key[ nextEntry() ]; }
-+  public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractIntSortedSet {
-+  public IntListIterator iterator( final int from ) {
-+   return new KeyIterator( from );
-+  }
-+  public IntListIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( int k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( int k ) {
-+   final int oldSize = size;
-+   Int2ObjectLinkedOpenHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Int2ObjectLinkedOpenHashMap.this.clear();
-+  }
-+  public int firstInt() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return key[ first ];
-+  }
-+  public int lastInt() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return key[ last ];
-+  }
-+  public IntComparator comparator() { return null; }
-+  final public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
-+  final public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
-+  final public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
-+ }
-+ public IntSortedSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
-+  public V previous() { return value[ previousEntry() ]; }
-+  public void set( V v ) { throw new UnsupportedOperationException(); }
-+  public void add( V v ) { throw new UnsupportedOperationException(); }
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Int2ObjectLinkedOpenHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final int newKey[] = new int[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = first, prev = -1, newPrev = -1, t, pos;
-+  final long link[] = this.link;
-+  final long newLink[] = new long[ newN + 1 ];
-+  first = -1;
-+  for( int j = size; j-- != 0; ) {
-+   if ( ( (key[ i ]) == (0) ) ) pos = newN;
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
-+    while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+   if ( prev != -1 ) {
-+    newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    newPrev = pos;
-+   }
-+   else {
-+    newPrev = first = pos;
-+    // Special case of SET(newLink[ pos ], -1, -1);
-+    newLink[ pos ] = -1L;
-+   }
-+   t = i;
-+   i = (int) link[ i ];
-+   prev = t;
-+  }
-+  this.link = newLink;
-+  this.last = newPrev;
-+  if ( newPrev != -1 )
-+   // Special case of SET_NEXT( newLink[ newPrev ], -1 );
-+   newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectLinkedOpenHashMap <V> clone() {
-+  Int2ObjectLinkedOpenHashMap <V> c;
-+  try {
-+   c = (Int2ObjectLinkedOpenHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  c.link = link.clone();
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = (key[ i ]);
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeInt( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final int key[] = this.key = new int[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  final long link[] = this.link = new long[ n + 1 ];
-+  int prev = -1;
-+  first = last = -1;
-+  int k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readInt();
-+   v = (V) s.readObject();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+   if ( first != -1 ) {
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    prev = pos;
-+   }
-+   else {
-+    prev = first = pos;
-+    // Special case of SET_PREV( newLink[ pos ], -1 );
-+    link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
-+   }
-+  }
-+  last = prev;
-+  if ( prev != -1 )
-+   // Special case of SET_NEXT( link[ prev ], -1 );
-+   link[ prev ] |= -1 & 0xFFFFFFFFL;
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Map;
-+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
-+ *
-+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
-+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
-+ *
-+ * <P>A submap or subset may or may not have an
-+ * independent default return value (which however must be initialized to the
-+ * default return value of the originator).
-+ *
-+ * @see Map
-+ */
-+public interface Int2ObjectMap <V> extends Int2ObjectFunction <V>, Map<Integer,V> {
-+ /** An entry set providing fast iteration. 
-+	 *
-+	 * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
-+	 * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
-+	 * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
-+	 * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
-+	 * by returning always the same entry</em> (of course, mutated).
-+	 */
-+ public interface FastEntrySet <V> extends ObjectSet<Int2ObjectMap.Entry <V> > {
-+  /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
-+		 *
-+		 * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
-+		 */
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator();
-+ }
-+ /** Returns a set view of the mappings contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
-+	 *
-+	 * @return a set view of the mappings contained in this map.
-+	 * @see Map#entrySet()
-+	 */
-+ ObjectSet<Map.Entry<Integer, V>> entrySet();
-+ /** Returns a type-specific set view of the mappings contained in this map.
-+	 *
-+	 * <p>This method is necessary because there is no inheritance along
-+	 * type parameters: it is thus impossible to strengthen {@link #entrySet()}
-+	 * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
-+	 * of type-specific entries (the latter makes it possible to
-+	 * access keys and values with type-specific methods).
-+	 *
-+	 * @return a type-specific set view of the mappings contained in this map.
-+	 * @see #entrySet()
-+	 */
-+ ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
-+ /** Returns a set view of the keys contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
-+	 *
-+	 * @return a set view of the keys contained in this map.
-+	 * @see Map#keySet()
-+	 */
-+ IntSet keySet();
-+ /** Returns a set view of the values contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#values()}.
-+	 *
-+	 * @return a set view of the values contained in this map.
-+	 * @see Map#values()
-+	 */
-+ ObjectCollection <V> values();
-+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
-+	 *  that use polymorphism to avoid (un)boxing.
-+	 *
-+	 * @see java.util.Map.Entry
-+	 */
-+ interface Entry <V> extends Map.Entry <Integer,V> {
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  Integer getKey();
-+  /**
-+		 * @see java.util.Map.Entry#getKey()
-+		 */
-+  int getIntKey();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectSets;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectCollections;
-+import java.util.Map;
-+/** A class providing static methods and objects that do useful things with type-specific maps.
-+ *
-+ * @see it.unimi.dsi.fastutil.Maps
-+ * @see java.util.Collections
-+ */
-+public class Int2ObjectMaps {
-+ private Int2ObjectMaps() {}
-+ /** An immutable class representing an empty type-specific map.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific map.
-+	 */
-+ public static class EmptyMap <V> extends Int2ObjectFunctions.EmptyFunction <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyMap() {}
-+  public boolean containsValue( final Object v ) { return false; }
-+  public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
-+ 
-+  public IntSet keySet() { return IntSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
-+        private Object readResolve() { return EMPTY_MAP; }
-+  public Object clone() { return EMPTY_MAP; }
-+  public boolean isEmpty() { return true; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
-+  public int hashCode() { return 0; }
-+  public boolean equals( final Object o ) {
-+   if ( ! ( o instanceof Map ) ) return false;
-+   return ((Map<?,?>)o).isEmpty();
-+  }
-+  public String toString() { return "{}"; }
-+ }
-+ /** An empty type-specific map (immutable). It is serializable and cloneable. 
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
-+ /** Return an empty map (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
-+	 * @return an empty map (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <V> Int2ObjectMap <V> emptyMap() {
-+  return EMPTY_MAP;
-+ }
-+ /** An immutable class representing a type-specific singleton map.	 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific map.
-+	 */
-+ public static class Singleton <V> extends Int2ObjectFunctions.Singleton <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
-+  protected transient IntSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected Singleton( final int key, final V value ) {
-+   super( key, value );
-+  }
-+  public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
-+  public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
-+  public IntSet keySet() { if ( keys == null ) keys = IntSets.singleton( key ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
-+  protected class SingletonEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer,V> {
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+   public Integer getKey() { return (Integer.valueOf(Singleton.this.key)); }
-+   public V getValue() { return (Singleton.this.value); }
-+   public int getIntKey() { return Singleton.this.key; }
-+   public V setValue( final V value ) { throw new UnsupportedOperationException(); }
-+   public boolean equals( final Object o ) {
-+    if (!(o instanceof Map.Entry)) return false;
-+    Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-+    return ( (Singleton.this.key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
-+   }
-+   public int hashCode() { return (Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
-+   public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
-+  }
-+  public boolean isEmpty() { return false; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
-+  public int hashCode() { return (key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
-+  public boolean equals( final Object o ) {
-+   if ( o == this ) return true;
-+   if ( ! ( o instanceof Map ) ) return false;
-+   Map<?,?> m = (Map<?,?>)o;
-+   if ( m.size() != 1 ) return false;
-+   return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
-+  }
-+  public String toString() { return "{" + key + "=>" + value + "}"; }
-+ }
-+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned map.
-+	 * @param value the only value of the returned map.
-+	 * @return a type-specific immutable map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectMap <V> singleton( final int key, V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned map.
-+	 * @param value the only value of the returned map.
-+	 * @return a type-specific immutable map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectMap <V> singleton( final Integer key, final V value ) {
-+  return new Singleton <V>( ((key).intValue()), (value) );
-+ }
-+ /** A synchronized wrapper class for maps. */
-+ public static class SynchronizedMap <V> extends Int2ObjectFunctions.SynchronizedFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectMap <V> map;
-+  protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
-+  protected transient IntSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected SynchronizedMap( final Int2ObjectMap <V> m, final Object sync ) {
-+   super( m, sync );
-+   this.map = m;
-+  }
-+  protected SynchronizedMap( final Int2ObjectMap <V> m ) {
-+   super( m );
-+   this.map = m;
-+  }
-+  public int size() { synchronized( sync ) { return map.size(); } }
-+  public boolean containsKey( final int k ) { synchronized( sync ) { return map.containsKey( k ); } }
-+  public boolean containsValue( final Object v ) { synchronized( sync ) { return map.containsValue( v ); } }
-+  public V defaultReturnValue() { synchronized( sync ) { return map.defaultReturnValue(); } }
-+  public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { map.defaultReturnValue( defRetValue ); } }
-+  public V put( final int k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
-+  //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { synchronized( sync ) { map.putAll( c ); } }
-+  public void putAll( final Map<? extends Integer, ? extends V> m ) { synchronized( sync ) { map.putAll( m ); } }
-+  public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.synchronize( map.int2ObjectEntrySet(), sync ); return entries; }
-+  public IntSet keySet() { if ( keys == null ) keys = IntSets.synchronize( map.keySet(), sync ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.synchronize( map.values(), sync ); return values; }
-+  public void clear() { synchronized( sync ) { map.clear(); } }
-+  public String toString() { synchronized( sync ) { return map.toString(); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V put( final Integer k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final int k ) { synchronized( sync ) { return map.remove( k ); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final int k ) { synchronized( sync ) { return map.get( k ); } }
-+  public boolean containsKey( final Object ok ) { synchronized( sync ) { return map.containsKey( ok ); } }
-+  public boolean isEmpty() { synchronized( sync ) { return map.isEmpty(); } }
-+  public ObjectSet<Map.Entry<Integer, V>> entrySet() { synchronized( sync ) { return map.entrySet(); } }
-+  public int hashCode() { synchronized( sync ) { return map.hashCode(); } }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return map.equals( o ); } }
-+ }
-+ /** Returns a synchronized type-specific map backed by the given type-specific map.
-+	 *
-+	 * @param m the map to be wrapped in a synchronized map.
-+	 * @return a synchronized view of the specified map.
-+	 * @see java.util.Collections#synchronizedMap(Map)
-+	 */
-+ public static <V> Int2ObjectMap <V> synchronize( final Int2ObjectMap <V> m ) { return new SynchronizedMap <V>( m ); }
-+ /** Returns a synchronized type-specific map backed by the given type-specific map, using an assigned object to synchronize.
-+	 *
-+	 * @param m the map to be wrapped in a synchronized map.
-+	 * @param sync an object that will be used to synchronize the access to the map.
-+	 * @return a synchronized view of the specified map.
-+	 * @see java.util.Collections#synchronizedMap(Map)
-+	 */
-+ public static <V> Int2ObjectMap <V> synchronize( final Int2ObjectMap <V> m, final Object sync ) { return new SynchronizedMap <V>( m, sync ); }
-+ /** An unmodifiable wrapper class for maps. */
-+ public static class UnmodifiableMap <V> extends Int2ObjectFunctions.UnmodifiableFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectMap <V> map;
-+  protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
-+  protected transient IntSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected UnmodifiableMap( final Int2ObjectMap <V> m ) {
-+   super( m );
-+   this.map = m;
-+  }
-+  public int size() { return map.size(); }
-+  public boolean containsKey( final int k ) { return map.containsKey( k ); }
-+  public boolean containsValue( final Object v ) { return map.containsValue( v ); }
-+  public V defaultReturnValue() { throw new UnsupportedOperationException(); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  public V put( final int k, final V v ) { throw new UnsupportedOperationException(); }
-+  //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { throw new UnsupportedOperationException(); }
-+  public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.unmodifiable( map.int2ObjectEntrySet() ); return entries; }
-+  public IntSet keySet() { if ( keys == null ) keys = IntSets.unmodifiable( map.keySet() ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.unmodifiable( map.values() ); return values; }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return map.toString(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final int k ) { throw new UnsupportedOperationException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final int k ) { return map.get( k ); }
-+  public boolean containsKey( final Object ok ) { return map.containsKey( ok ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final Object k ) { return map.get( k ); }
-+  public boolean isEmpty() { return map.isEmpty(); }
-+  public ObjectSet<Map.Entry<Integer, V>> entrySet() { return ObjectSets.unmodifiable( map.entrySet() ); }
-+ }
-+ /** Returns an unmodifiable type-specific map backed by the given type-specific map.
-+	 *
-+	 * @param m the map to be wrapped in an unmodifiable map.
-+	 * @return an unmodifiable view of the specified map.
-+	 * @see java.util.Collections#unmodifiableMap(Map)
-+	 */
-+ public static <V> Int2ObjectMap <V> unmodifiable( final Int2ObjectMap <V> m ) { return new UnmodifiableMap <V>( m ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
-+ * is specified at creation time.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Int2ObjectOpenCustomHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient int[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The hash strategy of this custom map. */
-+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient IntSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this.strategy = strategy;
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new int[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( expected, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( m.size(), f, strategy );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( m, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( m.size(), f, strategy );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param strategy the strategy.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( m, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( k.length, f, strategy );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param strategy the strategy.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Returns the hashing strategy.
-+	 *
-+	 * @return the hashing strategy of this custom hash map.
-+	 */
-+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
-+  return strategy;
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Integer,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final int k, final V v) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final int k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Integer ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).intValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  int curr;
-+  final int[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+  }
-+ }
-+
-+ public V remove( final int k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final int k = ((((Integer)(ok)).intValue()));
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Integer ok ) {
-+  if ( ok == null ) return null;
-+  final int k = ((ok).intValue());
-+  if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final int k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final int k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final int key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key[ index ]));
-+  }
-+  public int getIntKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   return ( strategy.equals( (key[ index ]), (((e.getKey()).intValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** An iterator over a hash map. */
-+ private class MapIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the entry with the null key. */
-+  boolean mustReturnNullKey = Int2ObjectOpenCustomHashMap.this.containsNullKey;
-+  /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
-+  IntArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNullKey ) {
-+    mustReturnNullKey = false;
-+    return last = n;
-+   }
-+   final int key[] = Int2ObjectOpenCustomHashMap.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     final int k = wrapped.getInt( - pos - 1 );
-+     int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+     while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
-+     return p;
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   int curr;
-+   final int[] key = Int2ObjectOpenCustomHashMap.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      value[ last ] = null;
-+      return;
-+     }
-+     slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+    value[ last ] = value[ pos ];
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    Int2ObjectOpenCustomHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public Int2ObjectMap.Entry <V> next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
-+  private final MapEntry entry = new MapEntry();
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   if ( ( strategy.equals( (k), (0) ) ) ) return ( Int2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   int curr;
-+   final int[] key = Int2ObjectOpenCustomHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   final V v = (e.getValue());
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   int curr;
-+   final int[] key = Int2ObjectOpenCustomHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (curr), (k) ) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( strategy.equals( (curr), (k) ) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Int2ObjectOpenCustomHashMap.this.clear();
-+  }
-+ }
-+ public FastEntrySet <V> int2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements IntIterator {
-+  public KeyIterator() { super(); }
-+  public int nextInt() { return key[ nextEntry() ]; }
-+  public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractIntSet {
-+  public IntIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( int k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( int k ) {
-+   final int oldSize = size;
-+   Int2ObjectOpenCustomHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Int2ObjectOpenCustomHashMap.this.clear();
-+  }
-+ }
-+ public IntSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Int2ObjectOpenCustomHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final int newKey[] = new int[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+  }
-+  newValue[ newN ] = value[ n ];
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectOpenCustomHashMap <V> clone() {
-+  Int2ObjectOpenCustomHashMap <V> c;
-+  try {
-+   c = (Int2ObjectOpenCustomHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  c.strategy = strategy;
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = ( strategy.hashCode(key[ i ]) );
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeInt( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final int key[] = this.key = new int[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  int k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readInt();
-+   v = (V) s.readObject();
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+/** A type-specific hash map with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Int2ObjectOpenHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient int[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient IntSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectOpenHashMap( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new int[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 */
-+ public Int2ObjectOpenHashMap( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public Int2ObjectOpenHashMap() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 */
-+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 */
-+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectOpenHashMap( final int[] k, final V[] v, final float f ) {
-+  this( k.length, f );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectOpenHashMap( final int[] k, final V[] v ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Integer,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final int k, final V v) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final int k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Integer ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).intValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  int curr;
-+  final int[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+  }
-+ }
-+
-+ public V remove( final int k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final int k = ((((Integer)(ok)).intValue()));
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Integer ok ) {
-+  if ( ok == null ) return null;
-+  final int k = ((ok).intValue());
-+  if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final int k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final int k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final int key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key[ index ]));
-+  }
-+  public int getIntKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** An iterator over a hash map. */
-+ private class MapIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the entry with the null key. */
-+  boolean mustReturnNullKey = Int2ObjectOpenHashMap.this.containsNullKey;
-+  /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
-+  IntArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNullKey ) {
-+    mustReturnNullKey = false;
-+    return last = n;
-+   }
-+   final int key[] = Int2ObjectOpenHashMap.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     final int k = wrapped.getInt( - pos - 1 );
-+     int p = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
-+     while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
-+     return p;
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   int curr;
-+   final int[] key = Int2ObjectOpenHashMap.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      value[ last ] = null;
-+      return;
-+     }
-+     slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+    value[ last ] = value[ pos ];
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    Int2ObjectOpenHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public Int2ObjectMap.Entry <V> next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
-+  private final MapEntry entry = new MapEntry();
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   if ( ( (k) == (0) ) ) return ( Int2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   int curr;
-+   final int[] key = Int2ObjectOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final int k = ((e.getKey()).intValue());
-+   final V v = (e.getValue());
-+   if ( ( (k) == (0) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   int curr;
-+   final int[] key = Int2ObjectOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (curr) == (k) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (curr) == (k) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Int2ObjectOpenHashMap.this.clear();
-+  }
-+ }
-+ public FastEntrySet <V> int2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements IntIterator {
-+  public KeyIterator() { super(); }
-+  public int nextInt() { return key[ nextEntry() ]; }
-+  public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractIntSet {
-+  public IntIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( int k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( int k ) {
-+   final int oldSize = size;
-+   Int2ObjectOpenHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Int2ObjectOpenHashMap.this.clear();
-+  }
-+ }
-+ public IntSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Int2ObjectOpenHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final int newKey[] = new int[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+  }
-+  newValue[ newN ] = value[ n ];
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectOpenHashMap <V> clone() {
-+  Int2ObjectOpenHashMap <V> c;
-+  try {
-+   c = (Int2ObjectOpenHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = (key[ i ]);
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final int key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeInt( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final int key[] = this.key = new int[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  int k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readInt();
-+   v = (V) s.readObject();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Comparator;
-+import java.util.Iterator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+import java.util.NoSuchElementException;
-+/** A type-specific red-black tree map with a fast, small-footprint implementation.
-+ *
-+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
-+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
-+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
-+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
-+ *
-+ */
-+public class Int2ObjectRBTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
-+ /** A reference to the root entry. */
-+ protected transient Entry <V> tree;
-+ /** Number of entries in this map. */
-+ protected int count;
-+ /** The first key in this map. */
-+ protected transient Entry <V> firstEntry;
-+ /** The last key in this map. */
-+ protected transient Entry <V> lastEntry;
-+ /** Cached set of entries. */
-+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
-+ /** Cached set of keys. */
-+ protected transient IntSortedSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** The value of this variable remembers, after a <code>put()</code> 
-+	 * or a <code>remove()</code>, whether the <em>domain</em> of the map
-+	 * has been modified. */
-+ protected transient boolean modified;
-+ /** This map's comparator, as provided in the constructor. */
-+ protected Comparator<? super Integer> storedComparator;
-+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
-+		always a type-specific comparator, so it could be derived from the former by wrapping. */
-+ protected transient IntComparator actualComparator;
-+ private static final long serialVersionUID = -7046029254386353129L;
-+ private static final boolean ASSERTS = false;
-+ {
-+  allocatePaths();
-+ }
-+ /** Creates a new empty tree map. 
-+	 */
-+ public Int2ObjectRBTreeMap() {
-+  tree = null;
-+  count = 0;
-+ }
-+ /** Generates the comparator that will be actually used.
-+	 *
-+	 * <P>When a specific {@link Comparator} is specified and stored in {@link
-+	 * #storedComparator}, we must check whether it is type-specific.  If it is
-+	 * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
-+	 * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
-+	 * and makes it into a type-specific one.
-+	 */
-+ private void setActualComparator() {
-+  /* If the provided comparator is already type-specific, we use it. Otherwise,
-+		   we use a wrapper anonymous class to fake that it is type-specific. */
-+  if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
-+  else actualComparator = new IntComparator () {
-+    public int compare( int k1, int k2 ) {
-+     return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
-+    }
-+    public int compare( Integer ok1, Integer ok2 ) {
-+     return storedComparator.compare( ok1, ok2 );
-+    }
-+   };
-+ }
-+ /** Creates a new empty tree map with the given comparator.
-+	 *
-+	 * @param c a (possibly type-specific) comparator.
-+	 */
-+ public Int2ObjectRBTreeMap( final Comparator<? super Integer> c ) {
-+  this();
-+  storedComparator = c;
-+  setActualComparator();
-+ }
-+ /** Creates a new tree map copying a given map.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectRBTreeMap( final Map<? extends Integer, ? extends V> m ) {
-+  this();
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
-+	 *
-+	 * @param m a {@link SortedMap} to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectRBTreeMap( final SortedMap<Integer,V> m ) {
-+  this( m.comparator() );
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given map.
-+	 *
-+	 * @param m a type-specific map to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectRBTreeMap( final Int2ObjectMap <? extends V> m ) {
-+  this();
-+  putAll( m );
-+ }
-+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
-+	 *
-+	 * @param m a type-specific sorted map to be copied into the new tree map. 
-+	 */
-+ public Int2ObjectRBTreeMap( final Int2ObjectSortedMap <V> m ) {
-+  this( m.comparator() );
-+  putAll( m );
-+ }
-+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
-+	 *
-+	 * @param k the array of keys of the new tree map.
-+	 * @param v the array of corresponding values in the new tree map.
-+	 * @param c a (possibly type-specific) comparator.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectRBTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
-+  this( c );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new tree map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new tree map.
-+	 * @param v the array of corresponding values in the new tree map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Int2ObjectRBTreeMap( final int[] k, final V v[] ) {
-+  this( k, v, null );
-+ }
-+ /*
-+	 * The following methods implements some basic building blocks used by
-+	 * all accessors.  They are (and should be maintained) identical to those used in RBTreeSet.drv.
-+	 *
-+	 * The put()/remove() code is derived from Ben Pfaff's GNU libavl
-+	 * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
-+	 * going on, you should have a look at the literate code contained therein
-+	 * first.  
-+	 */
-+ /** Compares two keys in the right way. 
-+	 *
-+	 * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
-+	 * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
-+	 *
-+	 * @param k1 the first key.
-+	 * @param k2 the second key.
-+	 * @return a number smaller than, equal to or greater than 0, as usual
-+	 * (i.e., when k1 &lt; k2, k1 = k2 or k1 &gt; k2, respectively).
-+	 */
-+
-+ final int compare( final int k1, final int k2 ) {
-+  return actualComparator == null ? ( Integer.compare((k1),(k2)) ) : actualComparator.compare( k1, k2 );
-+ }
-+ /** Returns the entry corresponding to the given key, if it is in the tree; <code>null</code>, otherwise.
-+	 *
-+	 * @param k the key to search for.
-+	 * @return the corresponding entry, or <code>null</code> if no entry with the given key exists.
-+	 */
-+ final Entry <V> findKey( final int k ) {
-+  Entry <V> e = tree;
-+  int cmp;
-+  while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) e = cmp < 0 ? e.left() : e.right();
-+  return e;
-+ }
-+ /** Locates a key.
-+	 *
-+	 * @param k a key.
-+	 * @return the last entry on a search for the given key; this will be
-+	 * the given key, if it present; otherwise, it will be either the smallest greater key or the greatest smaller key.
-+	 */
-+ final Entry <V> locateKey( final int k ) {
-+  Entry <V> e = tree, last = tree;
-+  int cmp = 0;
-+  while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) {
-+   last = e;
-+   e = cmp < 0 ? e.left() : e.right();
-+  }
-+  return cmp == 0 ? e : last;
-+ }
-+ /** This vector remembers the path and the direction followed during the
-+	 *  current insertion. It suffices for about 2<sup>32</sup> entries. */
-+ private transient boolean dirPath[];
-+ private transient Entry <V> nodePath[];
-+ @SuppressWarnings("unchecked")
-+ private void allocatePaths() {
-+  dirPath = new boolean[ 64 ];
-+  nodePath = new Entry[ 64 ];
-+ }
-+ public V put( final int k, final V v ) {
-+  Entry <V> e = add( k );
-+  final V oldValue = e.value;
-+  e.value = v;
-+  return oldValue;
-+ }
-+   /** Returns a node with key k in the balanced tree, creating one with defRetValue if necessary.
-+	*
-+	* @param k the key
-+	* @return a node with key k. If a node with key k already exists, then that node is returned,
-+	* 				otherwise a new node with defRetValue is created ensuring that the tree is balanced
-+						after creation of the node.
-+	*/
-+ private Entry <V> add( final int k ) {
-+    /* After execution of this method, modified is true iff a new entry has
-+    been inserted. */
-+  modified = false;
-+  int maxDepth = 0;
-+  Entry <V> e;
-+  if ( tree == null ) { // The case of the empty tree is treated separately.
-+   count++;
-+   e = tree = lastEntry = firstEntry = new Entry <V>( k, defRetValue );
-+  }
-+  else {
-+   Entry <V> p = tree;
-+   int cmp, i = 0;
-+   while( true ) {
-+    if ( ( cmp = compare( k, p.key ) ) == 0 ) {
-+     // We clean up the node path, or we could have stale references later.
-+     while( i-- != 0 ) nodePath[ i ] = null;
-+     return p;
-+    }
-+    nodePath[ i ] = p;
-+    if ( dirPath[ i++ ] = cmp > 0 ) {
-+     if ( p.succ() ) {
-+      count++;
-+      e = new Entry <V>( k, defRetValue );
-+      if ( p.right == null ) lastEntry = e;
-+      e.left = p;
-+      e.right = p.right;
-+      p.right( e );
-+      break;
-+     }
-+     p = p.right;
-+    }
-+    else {
-+     if ( p.pred() ) {
-+      count++;
-+      e = new Entry <V>( k, defRetValue );
-+      if ( p.left == null ) firstEntry = e;
-+      e.right = p;
-+      e.left = p.left;
-+      p.left( e );
-+      break;
-+     }
-+     p = p.left;
-+    }
-+   }
-+   modified = true;
-+   maxDepth = i--;
-+   while( i > 0 && ! nodePath[ i ].black() ) {
-+    if ( ! dirPath[ i - 1 ] ) {
-+     Entry <V> y = nodePath[ i - 1 ].right;
-+     if ( ! nodePath[ i - 1 ].succ() && ! y.black() ) {
-+      nodePath[ i ].black( true );
-+      y.black( true );
-+      nodePath[ i - 1 ].black( false );
-+      i -= 2;
-+     }
-+     else {
-+      Entry <V> x;
-+      if ( ! dirPath[ i ] ) y = nodePath[ i ];
-+      else {
-+       x = nodePath[ i ];
-+       y = x.right;
-+       x.right = y.left;
-+       y.left = x;
-+       nodePath[ i - 1 ].left = y;
-+       if ( y.pred() ) {
-+        y.pred( false );
-+        x.succ( y );
-+       }
-+      }
-+      x = nodePath[ i - 1 ];
-+      x.black( false );
-+      y.black( true );
-+      x.left = y.right;
-+      y.right = x;
-+      if ( i < 2 ) tree = y;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = y;
-+       else nodePath[ i - 2 ].left = y;
-+      }
-+      if ( y.succ() ) {
-+       y.succ( false );
-+       x.pred( y );
-+      }
-+      break;
-+     }
-+    }
-+    else {
-+     Entry <V> y = nodePath[ i - 1 ].left;
-+     if ( ! nodePath[ i - 1 ].pred() && ! y.black() ) {
-+      nodePath[ i ].black( true );
-+      y.black( true );
-+      nodePath[ i - 1 ].black( false );
-+      i -= 2;
-+     }
-+     else {
-+      Entry <V> x;
-+      if ( dirPath[ i ] ) y = nodePath[ i ];
-+      else {
-+       x = nodePath[ i ];
-+       y = x.left;
-+       x.left = y.right;
-+       y.right = x;
-+       nodePath[ i - 1 ].right = y;
-+       if ( y.succ() ) {
-+        y.succ( false );
-+        x.pred( y );
-+       }
-+      }
-+      x = nodePath[ i - 1 ];
-+      x.black( false );
-+      y.black( true );
-+      x.right = y.left;
-+      y.left = x;
-+      if ( i < 2 ) tree = y;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = y;
-+       else nodePath[ i - 2 ].left = y;
-+      }
-+      if ( y.pred() ){
-+       y.pred( false );
-+       x.succ( y );
-+      }
-+      break;
-+     }
-+    }
-+   }
-+  }
-+  tree.black( true );
-+  // We clean up the node path, or we could have stale references later.
-+  while( maxDepth-- != 0 ) nodePath[ maxDepth ] = null;
-+  if ( ASSERTS ) {
-+   checkNodePath();
-+   checkTree( tree, 0, -1 );
-+  }
-+  return e;
-+ }
-+ /* After execution of this method, {@link #modified} is true iff an entry
-+	has been deleted. */
-+
-+ public V remove( final int k ) {
-+  modified = false;
-+  if ( tree == null ) return defRetValue;
-+  Entry <V> p = tree;
-+  int cmp;
-+  int i = 0;
-+  final int kk = k;
-+  while( true ) {
-+   if ( ( cmp = compare( kk, p.key ) ) == 0 ) break;
-+   dirPath[ i ] = cmp > 0;
-+   nodePath[ i ] = p;
-+   if ( dirPath[ i++ ] ) {
-+    if ( ( p = p.right() ) == null ) {
-+     // We clean up the node path, or we could have stale references later.
-+     while( i-- != 0 ) nodePath[ i ] = null;
-+     return defRetValue;
-+    }
-+   }
-+   else {
-+    if ( ( p = p.left() ) == null ) {
-+     // We clean up the node path, or we could have stale references later.
-+     while( i-- != 0 ) nodePath[ i ] = null;
-+     return defRetValue;
-+    }
-+   }
-+  }
-+  if ( p.left == null ) firstEntry = p.next();
-+  if ( p.right == null ) lastEntry = p.prev();
-+  if ( p.succ() ) {
-+   if ( p.pred() ) {
-+    if ( i == 0 ) tree = p.left;
-+    else {
-+     if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].succ( p.right );
-+     else nodePath[ i - 1 ].pred( p.left );
-+    }
-+   }
-+   else {
-+    p.prev().right = p.right;
-+    if ( i == 0 ) tree = p.left;
-+    else {
-+     if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].right = p.left;
-+     else nodePath[ i - 1 ].left = p.left;
-+    }
-+   }
-+  }
-+  else {
-+   boolean color;
-+   Entry <V> r = p.right;
-+   if ( r.pred() ) {
-+    r.left = p.left;
-+    r.pred( p.pred() );
-+    if ( ! r.pred() ) r.prev().right = r;
-+    if ( i == 0 ) tree = r;
-+    else {
-+     if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].right = r;
-+     else nodePath[ i - 1 ].left = r;
-+    }
-+    color = r.black();
-+    r.black( p.black() );
-+    p.black( color );
-+    dirPath[ i ] = true;
-+    nodePath[ i++ ] = r;
-+   }
-+   else {
-+    Entry <V> s;
-+    int j = i++;
-+    while( true ) {
-+     dirPath[ i ] = false;
-+     nodePath[ i++ ] = r;
-+     s = r.left;
-+     if ( s.pred() ) break;
-+     r = s;
-+    }
-+    dirPath[ j ] = true;
-+    nodePath[ j ] = s;
-+    if ( s.succ() ) r.pred( s );
-+    else r.left = s.right;
-+    s.left = p.left;
-+    if ( ! p.pred() ) {
-+     p.prev().right = s;
-+     s.pred( false );
-+    }
-+    s.right( p.right );
-+    color = s.black();
-+    s.black( p.black() );
-+    p.black( color );
-+    if ( j == 0 ) tree = s;
-+    else {
-+     if ( dirPath[ j - 1 ] ) nodePath[ j - 1 ].right = s;
-+     else nodePath[ j - 1 ].left = s;
-+    }
-+   }
-+  }
-+  int maxDepth = i;
-+  if ( p.black() ) {
-+   for( ; i > 0; i-- ) {
-+    if ( dirPath[ i - 1 ] && ! nodePath[ i - 1 ].succ() ||
-+      ! dirPath[ i - 1 ] && ! nodePath[ i - 1 ].pred() ) {
-+     Entry <V> x = dirPath[ i - 1 ] ? nodePath[ i - 1 ].right : nodePath[ i - 1 ].left;
-+     if ( ! x.black() ) {
-+      x.black( true );
-+      break;
-+     }
-+    }
-+    if ( ! dirPath[ i - 1 ] ) {
-+     Entry <V> w = nodePath[ i - 1 ].right;
-+     if ( ! w.black() ) {
-+      w.black( true );
-+      nodePath[ i - 1 ].black( false );
-+      nodePath[ i - 1 ].right = w.left;
-+      w.left = nodePath[ i - 1 ];
-+      if ( i < 2 ) tree = w;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
-+       else nodePath[ i - 2 ].left = w;
-+      }
-+      nodePath[ i ] = nodePath[ i - 1 ];
-+      dirPath[ i ] = false;
-+      nodePath[ i - 1 ] = w;
-+      if ( maxDepth == i++ ) maxDepth++;
-+      w = nodePath[ i - 1 ].right;
-+     }
-+     if ( ( w.pred() || w.left.black() ) &&
-+       ( w.succ() || w.right.black() ) ) {
-+      w.black( false );
-+     }
-+     else {
-+      if ( w.succ() || w.right.black() ) {
-+       Entry <V> y = w.left;
-+       y.black ( true );
-+       w.black( false );
-+       w.left = y.right;
-+       y.right = w;
-+       w = nodePath[ i - 1 ].right = y;
-+       if ( w.succ() ) {
-+        w.succ( false );
-+        w.right.pred( w );
-+       }
-+      }
-+      w.black( nodePath[ i - 1 ].black() );
-+      nodePath[ i - 1 ].black( true );
-+      w.right.black( true );
-+      nodePath[ i - 1 ].right = w.left;
-+      w.left = nodePath[ i - 1 ];
-+      if ( i < 2 ) tree = w;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
-+       else nodePath[ i - 2 ].left = w;
-+      }
-+      if ( w.pred() ) {
-+       w.pred( false );
-+       nodePath[ i - 1 ].succ( w );
-+      }
-+      break;
-+     }
-+    }
-+    else {
-+     Entry <V> w = nodePath[ i - 1 ].left;
-+     if ( ! w.black() ) {
-+      w.black ( true );
-+      nodePath[ i - 1 ].black( false );
-+      nodePath[ i - 1 ].left = w.right;
-+      w.right = nodePath[ i - 1 ];
-+      if ( i < 2 ) tree = w;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
-+       else nodePath[ i - 2 ].left = w;
-+      }
-+      nodePath[ i ] = nodePath[ i - 1 ];
-+      dirPath[ i ] = true;
-+      nodePath[ i - 1 ] = w;
-+      if ( maxDepth == i++ ) maxDepth++;
-+      w = nodePath[ i - 1 ].left;
-+     }
-+     if ( ( w.pred() || w.left.black() ) &&
-+       ( w.succ() || w.right.black() ) ) {
-+      w.black( false );
-+     }
-+     else {
-+      if ( w.pred() || w.left.black() ) {
-+       Entry <V> y = w.right;
-+       y.black( true );
-+       w.black ( false );
-+       w.right = y.left;
-+       y.left = w;
-+       w = nodePath[ i - 1 ].left = y;
-+       if ( w.pred() ) {
-+        w.pred( false );
-+        w.left.succ( w );
-+       }
-+      }
-+      w.black( nodePath[ i - 1 ].black() );
-+      nodePath[ i - 1 ].black( true );
-+      w.left.black( true );
-+      nodePath[ i - 1 ].left = w.right;
-+      w.right = nodePath[ i - 1 ];
-+      if ( i < 2 ) tree = w;
-+      else {
-+       if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
-+       else nodePath[ i - 2 ].left = w;
-+      }
-+      if ( w.succ() ) {
-+       w.succ( false );
-+       nodePath[ i - 1 ].pred( w );
-+      }
-+      break;
-+     }
-+    }
-+   }
-+   if ( tree != null ) tree.black( true );
-+  }
-+  modified = true;
-+  count--;
-+  // We clean up the node path, or we could have stale references later.
-+  while( maxDepth-- != 0 ) nodePath[ maxDepth ] = null;
-+  if ( ASSERTS ) {
-+   checkNodePath();
-+   checkTree( tree, 0, -1 );
-+  }
-+  return p.value;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Integer ok, final V ov ) {
-+  final V oldValue = put( ((ok).intValue()), (ov) );
-+  return modified ? (this.defRetValue) : (oldValue);
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V remove( final Object ok ) {
-+  final V oldValue = remove( ((((Integer)(ok)).intValue())) );
-+  return modified ? (oldValue) : (this.defRetValue);
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final ValueIterator i = new ValueIterator();
-+  Object ev;
-+  int j = count;
-+  while( j-- != 0 ) {
-+   ev = i.next();
-+   if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
-+  }
-+  return false;
-+ }
-+ public void clear() {
-+  count = 0;
-+  tree = null;
-+  entries = null;
-+  values = null;
-+  keys = null;
-+  firstEntry = lastEntry = null;
-+ }
-+ /** This class represent an entry in a tree map.
-+	 *
-+	 * <P>We use the only "metadata", i.e., {@link Entry#info}, to store
-+	 * information about color, predecessor status and successor status.
-+	 *
-+	 * <P>Note that since the class is recursive, it can be
-+	 * considered equivalently a tree.
-+	 */
-+ private static final class Entry <V> implements Cloneable, Int2ObjectMap.Entry <V> {
-+  /** The the bit in this mask is true, the node is black. */
-+  private final static int BLACK_MASK = 1;
-+  /** If the bit in this mask is true, {@link #right} points to a successor. */
-+  private final static int SUCC_MASK = 1 << 31;
-+  /** If the bit in this mask is true, {@link #left} points to a predecessor. */
-+  private final static int PRED_MASK = 1 << 30;
-+  /** The key of this entry. */
-+  int key;
-+  /** The value of this entry. */
-+  V value;
-+  /** The pointers to the left and right subtrees. */
-+  Entry <V> left, right;
-+  /** This integers holds different information in different bits (see {@link #SUCC_MASK} and {@link #PRED_MASK}. */
-+  int info;
-+  Entry() {}
-+  /** Creates a new entry with the given key and value.
-+		 *
-+		 * @param k a key.
-+		 * @param v a value.
-+		 */
-+  Entry( final int k, final V v ) {
-+   this.key = k;
-+   this.value = v;
-+   info = SUCC_MASK | PRED_MASK;
-+  }
-+  /** Returns the left subtree. 
-+		 *
-+		 * @return the left subtree (<code>null</code> if the left
-+		 * subtree is empty).
-+		 */
-+  Entry <V> left() {
-+   return ( info & PRED_MASK ) != 0 ? null : left;
-+  }
-+  /** Returns the right subtree. 
-+		 *
-+		 * @return the right subtree (<code>null</code> if the right
-+		 * subtree is empty).
-+		 */
-+  Entry <V> right() {
-+   return ( info & SUCC_MASK ) != 0 ? null : right;
-+  }
-+  /** Checks whether the left pointer is really a predecessor.
-+		 * @return true if the left pointer is a predecessor.
-+		 */
-+  boolean pred() {
-+   return ( info & PRED_MASK ) != 0;
-+  }
-+  /** Checks whether the right pointer is really a successor.
-+		 * @return true if the right pointer is a successor.
-+		 */
-+  boolean succ() {
-+   return ( info & SUCC_MASK ) != 0;
-+  }
-+  /** Sets whether the left pointer is really a predecessor.
-+		 * @param pred if true then the left pointer will be considered a predecessor.
-+		 */
-+  void pred( final boolean pred ) {
-+   if ( pred ) info |= PRED_MASK;
-+   else info &= ~PRED_MASK;
-+  }
-+  /** Sets whether the right pointer is really a successor.
-+		 * @param succ if true then the right pointer will be considered a successor.
-+		 */
-+  void succ( final boolean succ ) {
-+   if ( succ ) info |= SUCC_MASK;
-+   else info &= ~SUCC_MASK;
-+  }
-+  /** Sets the left pointer to a predecessor.
-+		 * @param pred the predecessr.
-+		 */
-+  void pred( final Entry <V> pred ) {
-+   info |= PRED_MASK;
-+   left = pred;
-+  }
-+  /** Sets the right pointer to a successor.
-+		 * @param succ the successor.
-+		 */
-+  void succ( final Entry <V> succ ) {
-+   info |= SUCC_MASK;
-+   right = succ;
-+  }
-+  /** Sets the left pointer to the given subtree.
-+		 * @param left the new left subtree.
-+		 */
-+  void left( final Entry <V> left ) {
-+   info &= ~PRED_MASK;
-+   this.left = left;
-+  }
-+  /** Sets the right pointer to the given subtree.
-+		 * @param right the new right subtree.
-+		 */
-+  void right( final Entry <V> right ) {
-+   info &= ~SUCC_MASK;
-+   this.right = right;
-+  }
-+  /** Returns whether this node is black.
-+		 * @return true iff this node is black.
-+		 */
-+  boolean black() {
-+   return ( info & BLACK_MASK ) != 0;
-+  }
-+  /** Sets whether this node is black.
-+		 * @param black if true, then this node becomes black; otherwise, it becomes red..
-+		 */
-+  void black( final boolean black ) {
-+   if ( black ) info |= BLACK_MASK;
-+   else info &= ~BLACK_MASK;
-+  }
-+  /** Computes the next entry in the set order.
-+		 *
-+		 * @return the next entry (<code>null</code>) if this is the last entry).
-+		 */
-+  Entry <V> next() {
-+   Entry <V> next = this.right;
-+   if ( ( info & SUCC_MASK ) == 0 ) while ( ( next.info & PRED_MASK ) == 0 ) next = next.left;
-+   return next;
-+  }
-+  /** Computes the previous entry in the set order.
-+		 *
-+		 * @return the previous entry (<code>null</code>) if this is the first entry).
-+		 */
-+  Entry <V> prev() {
-+   Entry <V> prev = this.left;
-+   if ( ( info & PRED_MASK ) == 0 ) while ( ( prev.info & SUCC_MASK ) == 0 ) prev = prev.right;
-+   return prev;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer getKey() {
-+   return (Integer.valueOf(key));
-+  }
-+  public int getIntKey() {
-+   return key;
-+  }
-+  public V getValue() {
-+   return (value);
-+  }
-+  public V setValue(final V value) {
-+   final V oldValue = this.value;
-+   this.value = value;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public Entry <V> clone() {
-+   Entry <V> c;
-+   try {
-+    c = (Entry <V>)super.clone();
-+   }
-+   catch(CloneNotSupportedException cantHappen) {
-+    throw new InternalError();
-+   }
-+   c.key = key;
-+   c.value = value;
-+   c.info = info;
-+   return c;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
-+   return ( (key) == (((e.getKey()).intValue())) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
-+  }
-+  public String toString() {
-+   return key + "=>" + value;
-+  }
-+  /*
-+		  public void prettyPrint() {
-+		  prettyPrint(0);
-+		  }
-+
-+		  public void prettyPrint(int level) {
-+		  if ( pred() ) {
-+		  for (int i = 0; i < level; i++)
-+		  System.err.print("  ");
-+		  System.err.println("pred: " + left );
-+		  }
-+		  else if (left != null)
-+		  left.prettyPrint(level +1 );
-+		  for (int i = 0; i < level; i++)
-+		  System.err.print("  ");
-+		  System.err.println(key + "=" + value + " (" + balance() + ")");
-+		  if ( succ() ) {
-+		  for (int i = 0; i < level; i++)
-+		  System.err.print("  ");
-+		  System.err.println("succ: " + right );
-+		  }
-+		  else if (right != null)
-+		  right.prettyPrint(level + 1);
-+		  }*/
-+ }
-+ /*
-+	  public void prettyPrint() {
-+	  System.err.println("size: " + count);
-+	  if (tree != null) tree.prettyPrint();
-+	  }*/
-+
-+ public boolean containsKey( final int k ) {
-+  return findKey( k ) != null;
-+ }
-+ public int size() {
-+  return count;
-+ }
-+ public boolean isEmpty() {
-+  return count == 0;
-+ }
-+
-+ public V get( final int k ) {
-+  final Entry <V> e = findKey( k );
-+  return e == null ? defRetValue : e.value;
-+ }
-+ public int firstIntKey() {
-+  if ( tree == null ) throw new NoSuchElementException();
-+  return firstEntry.key;
-+ }
-+ public int lastIntKey() {
-+  if ( tree == null ) throw new NoSuchElementException();
-+  return lastEntry.key;
-+ }
-+ /** An abstract iterator on the whole range.
-+	 *
-+	 * <P>This class can iterate in both directions on a threaded tree.
-+	 */
-+ private class TreeIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  Entry <V> prev;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  Entry <V> next;
-+  /** The last entry that was returned (or <code>null</code> if we did not iterate or used {@link #remove()}). */
-+  Entry <V> curr;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this {@link TreeIterator} has been created using the nonempty constructor.*/
-+  int index = 0;
-+  TreeIterator() {
-+   next = firstEntry;
-+  }
-+  TreeIterator( final int k ) {
-+   if ( ( next = locateKey( k ) ) != null ) {
-+    if ( compare( next.key, k ) <= 0 ) {
-+     prev = next;
-+     next = next.next();
-+    }
-+    else prev = next.prev();
-+   }
-+  }
-+  public boolean hasNext() { return next != null; }
-+  public boolean hasPrevious() { return prev != null; }
-+  void updateNext() {
-+   next = next.next();
-+  }
-+  Entry <V> nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = prev = next;
-+   index++;
-+   updateNext();
-+   return curr;
-+  }
-+  void updatePrevious() {
-+   prev = prev.prev();
-+  }
-+  Entry <V> previousEntry() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = next = prev;
-+   index--;
-+   updatePrevious();
-+   return curr;
-+  }
-+  public int nextIndex() {
-+   return index;
-+  }
-+  public int previousIndex() {
-+   return index - 1;
-+  }
-+  public void remove() {
-+   if ( curr == null ) throw new IllegalStateException();
-+   /* If the last operation was a next(), we are removing an entry that preceeds
-+			   the current index, and thus we must decrement it. */
-+   if ( curr == prev ) index--;
-+   next = prev = curr;
-+   updatePrevious();
-+   updateNext();
-+   Int2ObjectRBTreeMap.this.remove( curr.key );
-+   curr = null;
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+  public int back( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasPrevious() ) previousEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ /** An iterator on the whole range.
-+	 *
-+	 * <P>This class can iterate in both directions on a threaded tree.
-+	 */
-+ private class EntryIterator extends TreeIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+  EntryIterator() {}
-+  EntryIterator( final int k ) {
-+   super( k );
-+  }
-+  public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
-+  public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
-+  public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
-+  if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
-+    final Comparator<? super Int2ObjectMap.Entry <V> > comparator = new Comparator<Int2ObjectMap.Entry <V> > () {
-+     public int compare( final Int2ObjectMap.Entry <V> x, Int2ObjectMap.Entry <V> y ) {
-+      return Int2ObjectRBTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() );
-+     }
-+    };
-+    public Comparator<? super Int2ObjectMap.Entry <V> > comparator() {
-+     return comparator;
-+    }
-+    public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
-+     return new EntryIterator();
-+    }
-+    public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
-+     return new EntryIterator( from.getIntKey() );
-+    }
-+    @SuppressWarnings("unchecked")
-+    public boolean contains( final Object o ) {
-+     if (!(o instanceof Map.Entry)) return false;
-+     final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+     if ( e.getKey() == null ) return false;
-+     final Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+     return e.equals( f );
-+    }
-+    @SuppressWarnings("unchecked")
-+    public boolean remove( final Object o ) {
-+     if (!(o instanceof Map.Entry)) return false;
-+     final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+     if ( e.getKey() == null ) return false;
-+     final Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+     if ( f != null ) Int2ObjectRBTreeMap.this.remove( f.key );
-+     return f != null;
-+    }
-+    public int size() { return count; }
-+    public void clear() { Int2ObjectRBTreeMap.this.clear(); }
-+    public Int2ObjectMap.Entry <V> first() { return firstEntry; }
-+    public Int2ObjectMap.Entry <V> last() { return lastEntry; }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
-+    public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
-+   };
-+  return entries;
-+ }
-+ /** An iterator on the whole range of keys.
-+	 *
-+	 * <P>This class can iterate in both directions on the keys of a threaded tree. We 
-+	 * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
-+	 * their type-specific counterparts) so that they return keys instead of entries.
-+	 */
-+ private final class KeyIterator extends TreeIterator implements IntListIterator {
-+  public KeyIterator() {}
-+  public KeyIterator( final int k ) { super( k ); }
-+  public int nextInt() { return nextEntry().key; }
-+  public int previousInt() { return previousEntry().key; }
-+  public void set( int k ) { throw new UnsupportedOperationException(); }
-+  public void add( int k ) { throw new UnsupportedOperationException(); }
-+  public Integer next() { return (Integer.valueOf(nextEntry().key)); }
-+  public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
-+  public void set( Integer ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Integer ok ) { throw new UnsupportedOperationException(); }
-+ };
-+ /** A keyset implementation using a more direct implementation for iterators. */
-+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
-+  public IntBidirectionalIterator iterator() { return new KeyIterator(); }
-+  public IntBidirectionalIterator iterator( final int from ) { return new KeyIterator( from ); }
-+ }
-+ /** Returns a type-specific sorted set view of the keys contained in this map.
-+	 *
-+	 * <P>In addition to the semantics of {@link java.util.Map#keySet()}, you can
-+	 * safely cast the set returned by this call to a type-specific sorted
-+	 * set interface.
-+	 *
-+	 * @return a type-specific sorted set view of the keys contained in this map.
-+	 */
-+ public IntSortedSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on the whole range of values.
-+	 *
-+	 * <P>This class can iterate in both directions on the values of a threaded tree. We 
-+	 * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
-+	 * their type-specific counterparts) so that they return values instead of entries.
-+	 */
-+ private final class ValueIterator extends TreeIterator implements ObjectListIterator <V> {
-+  public V next() { return nextEntry().value; }
-+  public V previous() { return previousEntry().value; }
-+  public void set( V v ) { throw new UnsupportedOperationException(); }
-+  public void add( V v ) { throw new UnsupportedOperationException(); }
-+ };
-+ /** Returns a type-specific collection view of the values contained in this map.
-+	 *
-+	 * <P>In addition to the semantics of {@link java.util.Map#values()}, you can
-+	 * safely cast the collection returned by this call to a type-specific collection
-+	 * interface.
-+	 *
-+	 * @return a type-specific collection view of the values contained in this map.
-+	 */
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public boolean contains( final Object k ) {
-+     return containsValue( k );
-+    }
-+    public int size() {
-+     return count;
-+    }
-+    public void clear() {
-+     Int2ObjectRBTreeMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ public IntComparator comparator() {
-+  return actualComparator;
-+ }
-+ public Int2ObjectSortedMap <V> headMap( int to ) {
-+  return new Submap( (0), true, to, false );
-+ }
-+ public Int2ObjectSortedMap <V> tailMap( int from ) {
-+  return new Submap( from, false, (0), true );
-+ }
-+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
-+  return new Submap( from, false, to, false );
-+ }
-+ /** A submap with given range.
-+	 *
-+	 * <P>This class represents a submap. One has to specify the left/right
-+	 * limits (which can be set to -&infin; or &infin;). Since the submap is a
-+	 * view on the map, at a given moment it could happen that the limits of
-+	 * the range are not any longer in the main map. Thus, things such as
-+	 * {@link java.util.SortedMap#firstKey()} or {@link java.util.Collection#size()} must be always computed
-+	 * on-the-fly.  
-+	 */
-+ private final class Submap extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable {
-+     private static final long serialVersionUID = -7046029254386353129L;
-+  /** The start of the submap range, unless {@link #bottom} is true. */
-+  int from;
-+  /** The end of the submap range, unless {@link #top} is true. */
-+  int to;
-+  /** If true, the submap range starts from -&infin;. */
-+  boolean bottom;
-+  /** If true, the submap range goes to &infin;. */
-+  boolean top;
-+  /** Cached set of entries. */
-+  @SuppressWarnings("hiding")
-+  protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
-+  /** Cached set of keys. */
-+  @SuppressWarnings("hiding")
-+  protected transient IntSortedSet keys;
-+  /** Cached collection of values. */
-+  @SuppressWarnings("hiding")
-+  protected transient ObjectCollection <V> values;
-+  /** Creates a new submap with given key range.
-+		 *
-+		 * @param from the start of the submap range.
-+		 * @param bottom if true, the first parameter is ignored and the range starts from -&infin;.
-+		 * @param to the end of the submap range.
-+		 * @param top if true, the third parameter is ignored and the range goes to &infin;.
-+		 */
-+  public Submap( final int from, final boolean bottom, final int to, final boolean top ) {
-+   if ( ! bottom && ! top && Int2ObjectRBTreeMap.this.compare( from, to ) > 0 ) throw new IllegalArgumentException( "Start key (" + from + ") is larger than end key (" + to + ")" );
-+   this.from = from;
-+   this.bottom = bottom;
-+   this.to = to;
-+   this.top = top;
-+   this.defRetValue = Int2ObjectRBTreeMap.this.defRetValue;
-+  }
-+  public void clear() {
-+   final SubmapIterator i = new SubmapIterator();
-+   while( i.hasNext() ) {
-+    i.nextEntry();
-+    i.remove();
-+   }
-+  }
-+  /** Checks whether a key is in the submap range.
-+		 * @param k a key.
-+		 * @return true if is the key is in the submap range.
-+		 */
-+  final boolean in( final int k ) {
-+   return ( bottom || Int2ObjectRBTreeMap.this.compare( k, from ) >= 0 ) &&
-+    ( top || Int2ObjectRBTreeMap.this.compare( k, to ) < 0 );
-+  }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
-+   if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
-+     public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
-+      return new SubmapEntryIterator();
-+     }
-+     public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
-+      return new SubmapEntryIterator( from.getIntKey() );
-+     }
-+     public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return Int2ObjectRBTreeMap.this.int2ObjectEntrySet().comparator(); }
-+     @SuppressWarnings("unchecked")
-+     public boolean contains( final Object o ) {
-+      if (!(o instanceof Map.Entry)) return false;
-+      final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+      final Int2ObjectRBTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+      return f != null && in( f.key ) && e.equals( f );
-+     }
-+     @SuppressWarnings("unchecked")
-+     public boolean remove( final Object o ) {
-+      if (!(o instanceof Map.Entry)) return false;
-+      final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
-+      final Int2ObjectRBTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
-+      if ( f != null && in( f.key ) ) Submap.this.remove( f.key );
-+      return f != null;
-+     }
-+     public int size() {
-+      int c = 0;
-+      for( Iterator<?> i = iterator(); i.hasNext(); i.next() ) c++;
-+      return c;
-+     }
-+     public boolean isEmpty() { return ! new SubmapIterator().hasNext(); }
-+     public void clear() { Submap.this.clear(); }
-+     public Int2ObjectMap.Entry <V> first() { return firstEntry(); }
-+     public Int2ObjectMap.Entry <V> last() { return lastEntry(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
-+     public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
-+    };
-+   return entries;
-+  }
-+  private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
-+   public IntBidirectionalIterator iterator() { return new SubmapKeyIterator(); }
-+   public IntBidirectionalIterator iterator( final int from ) { return new SubmapKeyIterator( from ); }
-+  }
-+  public IntSortedSet keySet() {
-+   if ( keys == null ) keys = new KeySet();
-+   return keys;
-+  }
-+  public ObjectCollection <V> values() {
-+   if ( values == null ) values = new AbstractObjectCollection <V>() {
-+     public ObjectIterator <V> iterator() {
-+      return new SubmapValueIterator();
-+     }
-+     public boolean contains( final Object k ) {
-+      return containsValue( k );
-+     }
-+     public int size() {
-+      return Submap.this.size();
-+     }
-+     public void clear() {
-+      Submap.this.clear();
-+     }
-+    };
-+   return values;
-+  }
-+ 
-+  public boolean containsKey( final int k ) {
-+   return in( k ) && Int2ObjectRBTreeMap.this.containsKey( k );
-+  }
-+  public boolean containsValue( final Object v ) {
-+   final SubmapIterator i = new SubmapIterator();
-+   Object ev;
-+   while( i.hasNext() ) {
-+    ev = i.nextEntry().value;
-+    if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
-+   }
-+   return false;
-+  }
-+ 
-+  public V get(final int k) {
-+   final Int2ObjectRBTreeMap.Entry <V> e;
-+   final int kk = k;
-+   return in( kk ) && ( e = findKey( kk ) ) != null ? e.value : this.defRetValue;
-+  }
-+  public V put(final int k, final V v) {
-+   modified = false;
-+   if ( ! in( k ) ) throw new IllegalArgumentException( "Key (" + k + ") out of range [" + ( bottom ? "-" : String.valueOf( from ) ) + ", " + ( top ? "-" : String.valueOf( to ) ) + ")" );
-+   final V oldValue = Int2ObjectRBTreeMap.this.put( k, v );
-+   return modified ? this.defRetValue : oldValue;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V put( final Integer ok, final V ov ) {
-+   final V oldValue = put( ((ok).intValue()), (ov) );
-+   return modified ? (this.defRetValue) : (oldValue);
-+  }
-+ 
-+  public V remove( final int k ) {
-+   modified = false;
-+   if ( ! in( k ) ) return this.defRetValue;
-+   final V oldValue = Int2ObjectRBTreeMap.this.remove( k );
-+   return modified ? oldValue : this.defRetValue;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final Object ok ) {
-+   final V oldValue = remove( ((((Integer)(ok)).intValue())) );
-+   return modified ? (oldValue) : (this.defRetValue);
-+  }
-+  public int size() {
-+   final SubmapIterator i = new SubmapIterator();
-+   int n = 0;
-+   while( i.hasNext() ) {
-+    n++;
-+    i.nextEntry();
-+   }
-+   return n;
-+  }
-+  public boolean isEmpty() {
-+   return ! new SubmapIterator().hasNext();
-+  }
-+  public IntComparator comparator() {
-+   return actualComparator;
-+  }
-+  public Int2ObjectSortedMap <V> headMap( final int to ) {
-+   if ( top ) return new Submap( from, bottom, to, false );
-+   return compare( to, this.to ) < 0 ? new Submap( from, bottom, to, false ) : this;
-+  }
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) {
-+   if ( bottom ) return new Submap( from, false, to, top );
-+   return compare( from, this.from ) > 0 ? new Submap( from, false, to, top ) : this;
-+  }
-+  public Int2ObjectSortedMap <V> subMap( int from, int to ) {
-+   if ( top && bottom ) return new Submap( from, false, to, false );
-+   if ( ! top ) to = compare( to, this.to ) < 0 ? to : this.to;
-+   if ( ! bottom ) from = compare( from, this.from ) > 0 ? from : this.from;
-+   if ( ! top && ! bottom && from == this.from && to == this.to ) return this;
-+   return new Submap( from, false, to, false );
-+  }
-+  /** Locates the first entry.
-+		 *
-+		 * @return the first entry of this submap, or <code>null</code> if the submap is empty.
-+		 */
-+  public Int2ObjectRBTreeMap.Entry <V> firstEntry() {
-+   if ( tree == null ) return null;
-+   // If this submap goes to -infinity, we return the main map first entry; otherwise, we locate the start of the map.
-+   Int2ObjectRBTreeMap.Entry <V> e;
-+   if ( bottom ) e = firstEntry;
-+   else {
-+    e = locateKey( from );
-+    // If we find either the start or something greater we're OK.
-+    if ( compare( e.key, from ) < 0 ) e = e.next();
-+   }
-+   // Finally, if this submap doesn't go to infinity, we check that the resulting key isn't greater than the end.
-+   if ( e == null || ! top && compare( e.key, to ) >= 0 ) return null;
-+   return e;
-+  }
-+  /** Locates the last entry.
-+		 *
-+		 * @return the last entry of this submap, or <code>null</code> if the submap is empty.
-+		 */
-+  public Int2ObjectRBTreeMap.Entry <V> lastEntry() {
-+   if ( tree == null ) return null;
-+   // If this submap goes to infinity, we return the main map last entry; otherwise, we locate the end of the map.
-+   Int2ObjectRBTreeMap.Entry <V> e;
-+   if ( top ) e = lastEntry;
-+   else {
-+    e = locateKey( to );
-+    // If we find something smaller than the end we're OK.
-+    if ( compare( e.key, to ) >= 0 ) e = e.prev();
-+   }
-+   // Finally, if this submap doesn't go to -infinity, we check that the resulting key isn't smaller than the start.
-+   if ( e == null || ! bottom && compare( e.key, from ) < 0 ) return null;
-+   return e;
-+  }
-+  public int firstIntKey() {
-+   Int2ObjectRBTreeMap.Entry <V> e = firstEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.key;
-+  }
-+  public int lastIntKey() {
-+   Int2ObjectRBTreeMap.Entry <V> e = lastEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.key;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer firstKey() {
-+   Int2ObjectRBTreeMap.Entry <V> e = firstEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.getKey();
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer lastKey() {
-+   Int2ObjectRBTreeMap.Entry <V> e = lastEntry();
-+   if ( e == null ) throw new NoSuchElementException();
-+   return e.getKey();
-+  }
-+  /** An iterator for subranges.
-+		 * 
-+		 * <P>This class inherits from {@link TreeIterator}, but overrides the methods that
-+		 * update the pointer after a {@link java.util.ListIterator#next()} or {@link java.util.ListIterator#previous()}. If we would
-+		 * move out of the range of the submap we just overwrite the next or previous
-+		 * entry with <code>null</code>.
-+		 */
-+  private class SubmapIterator extends TreeIterator {
-+   SubmapIterator() {
-+    next = firstEntry();
-+   }
-+   SubmapIterator( final int k ) {
-+    this();
-+    if ( next != null ) {
-+     if ( ! bottom && compare( k, next.key ) < 0 ) prev = null;
-+     else if ( ! top && compare( k, ( prev = lastEntry() ).key ) >= 0 ) next = null;
-+     else {
-+      next = locateKey( k );
-+      if ( compare( next.key, k ) <= 0 ) {
-+       prev = next;
-+       next = next.next();
-+      }
-+      else prev = next.prev();
-+     }
-+    }
-+   }
-+   void updatePrevious() {
-+    prev = prev.prev();
-+    if ( ! bottom && prev != null && Int2ObjectRBTreeMap.this.compare( prev.key, from ) < 0 ) prev = null;
-+   }
-+   void updateNext() {
-+    next = next.next();
-+    if ( ! top && next != null && Int2ObjectRBTreeMap.this.compare( next.key, to ) >= 0 ) next = null;
-+   }
-+  }
-+  private class SubmapEntryIterator extends SubmapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
-+   SubmapEntryIterator() {}
-+   SubmapEntryIterator( final int k ) {
-+    super( k );
-+   }
-+   public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
-+   public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
-+   public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+   public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  }
-+  /** An iterator on a subrange of keys.
-+		 *
-+		 * <P>This class can iterate in both directions on a subrange of the
-+		 * keys of a threaded tree. We simply override the {@link
-+		 * java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
-+		 * type-specific counterparts) so that they return keys instead of
-+		 * entries.
-+		 */
-+  private final class SubmapKeyIterator extends SubmapIterator implements IntListIterator {
-+   public SubmapKeyIterator() { super(); }
-+   public SubmapKeyIterator( int from ) { super( from ); }
-+   public int nextInt() { return nextEntry().key; }
-+   public int previousInt() { return previousEntry().key; }
-+   public void set( int k ) { throw new UnsupportedOperationException(); }
-+   public void add( int k ) { throw new UnsupportedOperationException(); }
-+   public Integer next() { return (Integer.valueOf(nextEntry().key)); }
-+   public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
-+   public void set( Integer ok ) { throw new UnsupportedOperationException(); }
-+   public void add( Integer ok ) { throw new UnsupportedOperationException(); }
-+  };
-+  /** An iterator on a subrange of values.
-+		 *
-+		 * <P>This class can iterate in both directions on the values of a
-+		 * subrange of the keys of a threaded tree. We simply override the
-+		 * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
-+		 * type-specific counterparts) so that they return values instead of
-+		 * entries.  
-+		 */
-+  private final class SubmapValueIterator extends SubmapIterator implements ObjectListIterator <V> {
-+   public V next() { return nextEntry().value; }
-+   public V previous() { return previousEntry().value; }
-+   public void set( V v ) { throw new UnsupportedOperationException(); }
-+   public void add( V v ) { throw new UnsupportedOperationException(); }
-+  };
-+ }
-+ /** Returns a deep copy of this tree map.
-+	 *
-+	 * <P>This method performs a deep copy of this tree map; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 * @return a deep copy of this tree map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Int2ObjectRBTreeMap <V> clone() {
-+  Int2ObjectRBTreeMap <V> c;
-+  try {
-+   c = (Int2ObjectRBTreeMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.allocatePaths();
-+  if ( count != 0 ) {
-+   // Also this apparently unfathomable code is derived from GNU libavl.
-+   Entry <V> e, p, q, rp = new Entry <V>(), rq = new Entry <V>();
-+   p = rp;
-+   rp.left( tree );
-+   q = rq;
-+   rq.pred( null );
-+   while( true ) {
-+    if ( ! p.pred() ) {
-+     e = p.left.clone();
-+     e.pred( q.left );
-+     e.succ( q );
-+     q.left( e );
-+     p = p.left;
-+     q = q.left;
-+    }
-+    else {
-+     while( p.succ() ) {
-+      p = p.right;
-+      if ( p == null ) {
-+       q.right = null;
-+       c.tree = rq.left;
-+       c.firstEntry = c.tree;
-+       while( c.firstEntry.left != null ) c.firstEntry = c.firstEntry.left;
-+       c.lastEntry = c.tree;
-+       while( c.lastEntry.right != null ) c.lastEntry = c.lastEntry.right;
-+       return c;
-+      }
-+      q = q.right;
-+     }
-+     p = p.right;
-+     q = q.right;
-+    }
-+    if ( ! p.succ() ) {
-+     e = p.right.clone();
-+     e.succ( q.right );
-+     e.pred( q );
-+     q.right( e );
-+    }
-+   }
-+  }
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  int n = count;
-+  EntryIterator i = new EntryIterator();
-+  Entry <V> e;
-+  s.defaultWriteObject();
-+  while(n-- != 0) {
-+   e = i.nextEntry();
-+   s.writeInt( e.key );
-+   s.writeObject( e.value );
-+  }
-+ }
-+ /** Reads the given number of entries from the input stream, returning the corresponding tree. 
-+	 *
-+	 * @param s the input stream.
-+	 * @param n the (positive) number of entries to read.
-+	 * @param pred the entry containing the key that preceeds the first key in the tree.
-+	 * @param succ the entry containing the key that follows the last key in the tree.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ private Entry <V> readTree( final java.io.ObjectInputStream s, final int n, final Entry <V> pred, final Entry <V> succ ) throws java.io.IOException, ClassNotFoundException {
-+  if ( n == 1 ) {
-+   final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
-+   top.pred( pred );
-+   top.succ( succ );
-+   top.black( true );
-+   return top;
-+  }
-+  if ( n == 2 ) {
-+   /* We handle separately this case so that recursion will
-+			 *always* be on nonempty subtrees. */
-+   final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
-+   top.black( true );
-+   top.right( new Entry <V>( s.readInt(), (V) s.readObject() ) );
-+   top.right.pred( top );
-+   top.pred( pred );
-+   top.right.succ( succ );
-+   return top;
-+  }
-+  // The right subtree is the largest one.
-+  final int rightN = n / 2, leftN = n - rightN - 1;
-+  final Entry <V> top = new Entry <V>();
-+  top.left( readTree( s, leftN, pred, top ) );
-+  top.key = s.readInt();
-+  top.value = (V) s.readObject();
-+  top.black( true );
-+  top.right( readTree( s, rightN, top, succ ) );
-+  if ( n + 2 == ( ( n + 2 ) & -( n + 2 ) ) ) top.right.black( false ); // Quick test for determining whether n + 2 is a power of 2.
-+  return top;
-+ }
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  /* The storedComparator is now correctly set, but we must restore
-+		   on-the-fly the actualComparator. */
-+  setActualComparator();
-+  allocatePaths();
-+  if ( count != 0 ) {
-+   tree = readTree( s, count, null, null );
-+   Entry <V> e;
-+   e = tree;
-+   while( e.left() != null ) e = e.left();
-+   firstEntry = e;
-+   e = tree;
-+   while( e.right() != null ) e = e.right();
-+   lastEntry = e;
-+  }
-+  if ( ASSERTS ) checkTree( tree, 0, -1 );
-+ }
-+ private void checkNodePath() {}
-+ @SuppressWarnings("unused")
-+ private static <V> int checkTree( Entry <V> e, int d, int D ) { return 0; }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #entrySet()},
-+ * {@link #keySet()}, {@link #values()},
-+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
-+ *
-+ * @see SortedMap
-+ */
-+public interface Int2ObjectSortedMap <V> extends Int2ObjectMap <V>, SortedMap<Integer, V> {
-+ /** A sorted entry set providing fast iteration.
-+	 *
-+	 * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
-+	 * of a large number of entry objects. Some <code>fastutil</code>
-+	 * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
-+	 * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
-+	 * by returning always the same entry</em> (of course, mutated).
-+	 */
-+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Int2ObjectMap.Entry <V> >, FastEntrySet <V> {
-+  /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
-+		 *
-+		 * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
-+		 */
-+  public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( Int2ObjectMap.Entry <V> from );
-+ }
-+ /** Returns a sorted-set view of the mappings contained in this map.
-+	 *  Note that this specification strengthens the one given in the
-+	 *  corresponding type-specific unsorted map.
-+	 *
-+	 * @return a sorted-set view of the mappings contained in this map.
-+	 * @see Map#entrySet()
-+	 */
-+ ObjectSortedSet<Map.Entry<Integer, V>> entrySet();
-+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
-+	 * Note that this specification strengthens the one given in the
-+	 * corresponding type-specific unsorted map.
-+	 *
-+	 * @return a type-specific sorted-set view of the mappings contained in this map.
-+	 * @see #entrySet()
-+	 */
-+ ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
-+ /** Returns a sorted-set view of the keys contained in this map.
-+	 *  Note that this specification strengthens the one given in the
-+	 *  corresponding type-specific unsorted map.
-+	 *
-+	 * @return a sorted-set view of the keys contained in this map.
-+	 * @see Map#keySet()
-+	 */
-+ IntSortedSet keySet();
-+ /** Returns a set view of the values contained in this map.
-+	 * <P>Note that this specification strengthens the one given in {@link Map#values()},
-+	 * which was already strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link SortedMap}.
-+	 *
-+	 * @return a set view of the values contained in this map.
-+	 * @see Map#values()
-+	 */
-+ ObjectCollection <V> values();
-+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
-+	 *
-+	 * @see SortedMap#comparator()
-+	 */
-+ IntComparator comparator();
-+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
-+	 *
-+	 * @see SortedMap#subMap(Object,Object)
-+	 */
-+ Int2ObjectSortedMap <V> subMap(Integer fromKey, Integer toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
-+	 *
-+	 * @see SortedMap#headMap(Object)
-+	 */
-+ Int2ObjectSortedMap <V> headMap(Integer toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
-+	 *
-+	 * @see SortedMap#tailMap(Object)
-+	 */
-+ Int2ObjectSortedMap <V> tailMap(Integer fromKey);
-+ /**  Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
-+	 * @see SortedMap#subMap(Object,Object)
-+	 */
-+ Int2ObjectSortedMap <V> subMap(int fromKey, int toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
-+	 * @see SortedMap#headMap(Object)
-+	 */
-+ Int2ObjectSortedMap <V> headMap(int toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
-+	 * @see SortedMap#tailMap(Object)
-+	 */
-+ Int2ObjectSortedMap <V> tailMap(int fromKey);
-+ /**
-+	 * @see SortedMap#firstKey()
-+	 */
-+ int firstIntKey();
-+ /**
-+	 * @see SortedMap#lastKey()
-+	 */
-+ int lastIntKey();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
-+import java.util.Comparator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class Int2ObjectSortedMaps {
-+ private Int2ObjectSortedMaps() {}
-+ /** Returns a comparator for entries based on a given comparator on keys.
-+	 *
-+	 * @param comparator a comparator on keys.
-+	 * @return the associated comparator on entries.
-+	 */
-+ public static Comparator<? super Map.Entry<Integer, ?>> entryComparator( final IntComparator comparator ) {
-+  return new Comparator<Map.Entry<Integer, ?>>() {
-+   public int compare( Map.Entry<Integer, ?> x, Map.Entry<Integer, ?> y ) {
-+    return comparator.compare( x.getKey(), y.getKey() );
-+   }
-+  };
-+ }
-+ /** An immutable class representing an empty type-specific sorted map. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted map.
-+	 */
-+ public static class EmptySortedMap <V> extends Int2ObjectMaps.EmptyMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySortedMap() {}
-+  public IntComparator comparator() { return null; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
-+ 
-+  public IntSortedSet keySet() { return IntSortedSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> headMap( final int to ) { return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) { return EMPTY_MAP; }
-+  public int firstIntKey() { throw new NoSuchElementException(); }
-+  public int lastIntKey() { throw new NoSuchElementException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
-+ }
-+ /** An empty sorted map (immutable). It is serializable and cloneable. 
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
-+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
-+	 * @return an empty sorted map (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <V> Int2ObjectSortedMap <V> emptyMap() {
-+  return EMPTY_MAP;
-+ }
-+ /** An immutable class representing a type-specific singleton sorted map. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted map.
-+	 */
-+ public static class Singleton <V> extends Int2ObjectMaps.Singleton <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntComparator comparator;
-+  protected Singleton( final int key, final V value, IntComparator comparator ) {
-+   super( key, value );
-+   this.comparator = comparator;
-+  }
-+  protected Singleton( final int key, final V value ) {
-+   this( key, value, null );
-+  }
-+ 
-+  final int compare( final int k1, final int k2 ) {
-+   return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
-+  }
-+  public IntComparator comparator() { return comparator; }
-+ 
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Int2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
-+  public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.singleton( key, comparator ); return (IntSortedSet )keys; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> headMap( final int to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
-+  public int firstIntKey() { return key; }
-+  public int lastIntKey() { return key; }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> singleton( final Integer key, V value ) {
-+  return new Singleton <V>( ((key).intValue()), (value) );
-+ }
-+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @param comparator the comparator to use in the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> singleton( final Integer key, V value, IntComparator comparator ) {
-+  return new Singleton <V>( ((key).intValue()), (value), comparator );
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> singleton( final int key, final V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @param comparator the comparator to use in the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> singleton( final int key, final V value, IntComparator comparator ) {
-+  return new Singleton <V>( key, value, comparator );
-+ }
-+  /** A synchronized wrapper class for sorted maps. */
-+ public static class SynchronizedSortedMap <V> extends Int2ObjectMaps.SynchronizedMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectSortedMap <V> sortedMap;
-+  protected SynchronizedSortedMap( final Int2ObjectSortedMap <V> m, final Object sync ) {
-+   super( m, sync );
-+   sortedMap = m;
-+  }
-+  protected SynchronizedSortedMap( final Int2ObjectSortedMap <V> m ) {
-+   super( m );
-+   sortedMap = m;
-+  }
-+  public IntComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.int2ObjectEntrySet(), sync ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
-+  public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.synchronize( sortedMap.keySet(), sync ); return (IntSortedSet )keys; }
-+  public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
-+  public Int2ObjectSortedMap <V> headMap( final int to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
-+  public int firstIntKey() { synchronized( sync ) { return sortedMap.firstIntKey(); } }
-+  public int lastIntKey() { synchronized( sync ) { return sortedMap.lastIntKey(); } }
-+  public Integer firstKey() { synchronized( sync ) { return sortedMap.firstKey(); } }
-+  public Integer lastKey() { synchronized( sync ) { return sortedMap.lastKey(); } }
-+  public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
-+  public Int2ObjectSortedMap <V> headMap( final Integer to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
-+  public Int2ObjectSortedMap <V> tailMap( final Integer from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
-+ }
-+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map.
-+	 *
-+	 * @param m the sorted map to be wrapped in a synchronized sorted map.
-+	 * @return a synchronized view of the specified sorted map.
-+	 * @see java.util.Collections#synchronizedSortedMap(SortedMap)
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> synchronize( final Int2ObjectSortedMap <V> m ) { return new SynchronizedSortedMap <V>( m ); }
-+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map, using an assigned object to synchronize.
-+	 *
-+	 * @param m the sorted map to be wrapped in a synchronized sorted map.
-+	 * @param sync an object that will be used to synchronize the access to the sorted sorted map.
-+	 * @return a synchronized view of the specified sorted map.
-+	 * @see java.util.Collections#synchronizedSortedMap(SortedMap)
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> synchronize( final Int2ObjectSortedMap <V> m, final Object sync ) { return new SynchronizedSortedMap <V>( m, sync ); }
-+ /** An unmodifiable wrapper class for sorted maps. */
-+ public static class UnmodifiableSortedMap <V> extends Int2ObjectMaps.UnmodifiableMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Int2ObjectSortedMap <V> sortedMap;
-+  protected UnmodifiableSortedMap( final Int2ObjectSortedMap <V> m ) {
-+   super( m );
-+   sortedMap = m;
-+  }
-+  public IntComparator comparator() { return sortedMap.comparator(); }
-+  public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.int2ObjectEntrySet() ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
-+  public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.unmodifiable( sortedMap.keySet() ); return (IntSortedSet )keys; }
-+  public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
-+  public Int2ObjectSortedMap <V> headMap( final int to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
-+  public Int2ObjectSortedMap <V> tailMap( final int from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
-+  public int firstIntKey() { return sortedMap.firstIntKey(); }
-+  public int lastIntKey() { return sortedMap.lastIntKey(); }
-+  public Integer firstKey() { return sortedMap.firstKey(); }
-+  public Integer lastKey() { return sortedMap.lastKey(); }
-+  public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
-+  public Int2ObjectSortedMap <V> headMap( final Integer to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
-+  public Int2ObjectSortedMap <V> tailMap( final Integer from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
-+ }
-+ /** Returns an unmodifiable type-specific sorted map backed by the given type-specific sorted map.
-+	 *
-+	 * @param m the sorted map to be wrapped in an unmodifiable sorted map.
-+	 * @return an unmodifiable view of the specified sorted map.
-+	 * @see java.util.Collections#unmodifiableSortedMap(SortedMap)
-+	 */
-+ public static <V> Int2ObjectSortedMap <V> unmodifiable( final Int2ObjectSortedMap <V> m ) { return new UnmodifiableSortedMap <V>( m ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2010-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.io.Serializable;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based FIFO queue, supporting also deque operations.
-+ *
-+ * <P>Instances of this class represent a FIFO queue using a backing
-+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
-+ * to reduce its memory usage, if necessary.
-+ *
-+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
-+ */
-+public class IntArrayFIFOQueue extends AbstractIntPriorityQueue implements Serializable {
-+    private static final long serialVersionUID = 0L;
-+ /** The standard initial capacity of a queue. */
-+ public final static int INITIAL_CAPACITY = 4;
-+ /** The backing array. */
-+ protected transient int array[];
-+ /** The current (cached) length of {@link #array}. */
-+ protected transient int length;
-+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
-+ protected transient int start;
-+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
-+	 *  Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
-+ protected transient int end;
-+ /** Creates a new empty queue with given capacity.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+
-+ public IntArrayFIFOQueue( final int capacity ) {
-+  if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
-+  array = new int[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
-+  length = array.length;
-+ }
-+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
-+	 */
-+ public IntArrayFIFOQueue() {
-+  this( INITIAL_CAPACITY );
-+ }
-+ /** Returns <code>null</code> (FIFO queues have no comparator). 
-+	 * @return <code>null</code>.
-+	 */
-+ @Override
-+ public IntComparator comparator() {
-+  return null;
-+ }
-+ @Override
-+ public int dequeueInt() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  final int t = array[ start ];
-+  if ( ++start == length ) start = 0;
-+  reduce();
-+  return t;
-+ }
-+ /** Dequeues the last element from the queue.
-+	 *
-+	 * @return the dequeued element. 
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ public int dequeueLastInt() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  if ( end == 0 ) end = length;
-+  final int t = array[ --end ];
-+  reduce();
-+  return t;
-+ }
-+
-+ private final void resize( final int size, final int newLength ) {
-+  final int[] newArray = new int[ newLength ];
-+  if ( start >= end ) {
-+   if ( size != 0 ) {
-+    System.arraycopy( array, start, newArray, 0, length - start );
-+    System.arraycopy( array, 0, newArray, length - start, end );
-+   }
-+  }
-+  else System.arraycopy( array, start, newArray, 0, end - start );
-+  start = 0;
-+  end = size;
-+  array = newArray;
-+  length = newLength;
-+ }
-+ private final void expand() {
-+  resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
-+ }
-+ private final void reduce() {
-+  final int size = size();
-+  if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
-+ }
-+ @Override
-+ public void enqueue( int x ) {
-+  array[ end++ ] = x;
-+  if ( end == length ) end = 0;
-+  if ( end == start ) expand();
-+ }
-+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
-+	 */
-+ public void enqueueFirst( int x ) {
-+  if ( start == 0 ) start = length;
-+  array[ --start ] = x;
-+  if ( end == start ) expand();
-+ }
-+ /** Returns the first element of the queue. 
-+	 * @return the first element of the queue.	
-+	 */
-+ public int firstInt() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  return array[ start ];
-+ }
-+ /** Returns the last element of the queue. 
-+	 * @return the last element of the queue.	
-+	 */
-+ public int lastInt() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  return array[ ( end == 0 ? length : end ) - 1 ];
-+ }
-+ @Override
-+ public void clear() {
-+  start = end = 0;
-+ }
-+ /** Trims the queue to the smallest possible size. */
-+
-+ public void trim() {
-+  final int size = size();
-+  final int[] newArray =
-+           new int[ size + 1 ];
-+  if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
-+  else {
-+   System.arraycopy( array, start, newArray, 0, length - start );
-+   System.arraycopy( array, 0, newArray, length - start, end );
-+  }
-+  start = 0;
-+  length = ( end = size ) + 1;
-+  array = newArray;
-+ }
-+ @Override
-+ public int size() {
-+  final int apparentLength = end - start;
-+  return apparentLength >= 0 ? apparentLength : length + apparentLength;
-+ }
-+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  int size = size();
-+  s.writeInt( size );
-+  for( int i = start; size-- != 0; ) {
-+   s.writeInt( array[ i++ ] );
-+   if ( i == length ) i = 0;
-+  }
-+ }
-+
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  end = s.readInt();
-+  array = new int[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
-+  for( int i = 0; i < end; i++ ) array[ i ] = s.readInt();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based semi-indirect priority queue. 
-+ *
-+ * <P>Instances of this class use as reference list a <em>reference array</em>,
-+ * which must be provided to each constructor, and represent a priority queue
-+ * using a backing array of integer indices&mdash;all operations are performed
-+ * directly on the array. The array is enlarged as needed, but it is never
-+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
-+ *
-+ * <P>This implementation is extremely inefficient, but it is difficult to beat
-+ * when the size of the queue is very small. Moreover, it allows to enqueue several
-+ * time the same index, without limitations.
-+ */
-+public class IntArrayIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
-+ /** The reference array. */
-+ protected int refArray[];
-+ /** The backing array. */
-+ protected int array[] = IntArrays.EMPTY_ARRAY;
-+ /** The number of elements in this queue. */
-+ protected int size;
-+ /** The type-specific comparator used in this queue. */
-+ protected IntComparator c;
-+ /** The first index, cached, if {@link #firstIndexValid} is true. */
-+ protected int firstIndex;
-+ /** Whether {@link #firstIndex} contains a valid value. */
-+ protected boolean firstIndexValid;
-+ /** Creates a new empty queue without elements with a given capacity and comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
-+  if ( capacity > 0 ) this.array = new int[ capacity ];
-+  this.refArray = refArray;
-+  this.c = c;
-+ }
-+ /** Creates a new empty queue with given capacity and using the natural order.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity ) {
-+  this( refArray, capacity, null );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayIndirectPriorityQueue( int[] refArray, IntComparator c ) {
-+  this( refArray, refArray.length, c );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order. 
-+	 * @param refArray the reference array.
-+	 */
-+ public IntArrayIndirectPriorityQueue( int[] refArray ) {
-+  this( refArray, refArray.length, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
-+  this( refArray, 0, c );
-+  this.array = a;
-+  this.size = size;
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
-+  this( refArray, a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
-+  this( refArray, a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 */
-+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a ) {
-+  this( refArray, a, a.length );
-+ }
-+ /** Returns the index (in {@link #array}) of the smallest element. */
-+
-+ private int findFirst() {
-+  if ( firstIndexValid ) return this.firstIndex;
-+  firstIndexValid = true;
-+  int i = size;
-+  int firstIndex = --i;
-+  int first = refArray[ array[ firstIndex ] ];
-+  if ( c == null ) while( i-- != 0 ) { if ( ( (refArray[ array[ i ] ]) < (first) ) ) first = refArray[ array[ firstIndex = i ] ]; }
-+  else while( i-- != 0 ) { if ( c.compare( refArray[ array[ i ] ], first ) < 0 ) first = refArray[ array[ firstIndex = i ] ]; }
-+  return this.firstIndex = firstIndex;
-+ }
-+ /** Returns the index (in {@link #array}) of the largest element. */
-+
-+ private int findLast() {
-+  int i = size;
-+  int lastIndex = --i;
-+  int last = refArray[ array[ lastIndex ] ];
-+  if ( c == null ) { while( i-- != 0 ) if ( ( (last) < (refArray[ array[ i ] ]) ) ) last = refArray[ array[ lastIndex = i ] ]; }
-+  else { while( i-- != 0 ) if ( c.compare( last, refArray[ array[ i ] ] ) < 0 ) last = refArray[ array[ lastIndex = i ] ]; }
-+  return lastIndex;
-+ }
-+ protected final void ensureNonEmpty() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+ }
-+ /** Ensures that the given index is a firstIndexValid reference.
-+	 *
-+	 * @param index an index in the reference array.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
-+	 */
-+ protected void ensureElement( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
-+ }
-+ /** Enqueues a new element.
-+	 *
-+	 * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
-+	 * when <code>x</code> is already in the queue. However, the queue state will become
-+	 * inconsistent and the following behaviour will not be predictable.
-+	 */
-+
-+ public void enqueue( int x ) {
-+  ensureElement( x );
-+  if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
-+  if ( firstIndexValid ) {
-+   if ( c == null ) { if ( ( (refArray[ x ]) < (refArray[ array[ firstIndex ] ]) ) ) firstIndex = size; }
-+   else if ( c.compare( refArray[ x ], refArray[ array[ firstIndex ] ] ) < 0 ) firstIndex = size;
-+  }
-+  else firstIndexValid = false;
-+  array[ size++ ] = x;
-+ }
-+ public int dequeue() {
-+  ensureNonEmpty();
-+  final int firstIndex = findFirst();
-+  final int result = array[ firstIndex ];
-+  if ( --size != 0 ) System.arraycopy( array, firstIndex + 1, array, firstIndex, size - firstIndex );
-+  firstIndexValid = false;
-+  return result;
-+ }
-+ public int first() {
-+  ensureNonEmpty();
-+  return array[ findFirst() ];
-+ }
-+ public int last() {
-+  ensureNonEmpty();
-+  return array[ findLast() ];
-+ }
-+ public void changed() {
-+  ensureNonEmpty();
-+  firstIndexValid = false;
-+ }
-+ /** {@inheritDoc}
-+	 *
-+	 * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
-+	 * when <code>index</code> is not in the queue.
-+	 */
-+ public void changed( int index ) {
-+  ensureElement( index );
-+  if ( index == firstIndex ) firstIndexValid = false;
-+ }
-+ public void allChanged() {
-+  firstIndexValid = false;
-+ }
-+ public boolean remove( int index ) {
-+  ensureElement( index );
-+  final int[] a = array;
-+  int i = size;
-+  while( i-- != 0 ) if ( a[ i ] == index ) break;
-+  if ( i < 0 ) return false;
-+  firstIndexValid = false;
-+  if ( --size != 0 ) System.arraycopy( a, i + 1, a, i, size - i );
-+  return true;
-+ }
-+ public int front( int[] a ) {
-+  final int top = refArray[ array[ findFirst() ] ];
-+  int i = size, c = 0;
-+  while( i-- != 0 ) if ( ( (top) == (refArray[ array[ i ] ]) ) ) a[ c++ ] = array[ i ];
-+  return c;
-+ }
-+ public int size() { return size; }
-+ public void clear() { size = 0; firstIndexValid = false; }
-+ /** Trims the backing array so that it has exactly {@link #size()} elements.
-+	 */
-+ public void trim() {
-+  array = IntArrays.trim( array, size );
-+ }
-+ public IntComparator comparator() { return c; }
-+ public String toString() {
-+  StringBuffer s = new StringBuffer();
-+  s.append( "[" );
-+  for ( int i = 0; i < size; i++ ) {
-+   if ( i != 0 ) s.append( ", " );
-+   s.append( refArray[ array [ i ] ] );
-+  }
-+  s.append( "]" );
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.RandomAccess;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>This class implements a lightweight, fast, open, optimized,
-+ * reuse-oriented version of array-based lists. Instances of this class
-+ * represent a list with an array that is enlarged as needed when new entries
-+ * are created (by doubling its current length), but is
-+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
-+ * {@linkplain #trim() trimming methods} lets you control the size of the
-+ * backing array; this is particularly useful if you reuse instances of this class.
-+ * Range checks are equivalent to those of {@link java.util}'s classes, but
-+ * they are delayed as much as possible. The backing array is exposed by the
-+ * {@link #elements()} method.
-+ *
-+ * <p>This class implements the bulk methods <code>removeElements()</code>,
-+ * <code>addElements()</code> and <code>getElements()</code> using
-+ * high-performance system calls (e.g., {@link
-+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
-+ * expensive loops.
-+ *
-+ * @see java.util.ArrayList
-+ */
-+public class IntArrayList extends AbstractIntList implements RandomAccess, Cloneable, java.io.Serializable {
-+ private static final long serialVersionUID = -7046029254386353130L;
-+ /** The initial default capacity of an array list. */
-+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
-+ /** The backing array. */
-+ protected transient int a[];
-+ /** The current actual size of the list (never greater than the backing-array length). */
-+ protected int size;
-+ private static final boolean ASSERTS = false;
-+ /** Creates a new array list using a given array.
-+	 *
-+	 * <P>This constructor is only meant to be used by the wrapping methods.
-+	 *
-+	 * @param a the array that will be used to back this array list.
-+	 */
-+ @SuppressWarnings("unused")
-+ protected IntArrayList( final int a[], boolean dummy ) {
-+  this.a = a;
-+ }
-+ /** Creates a new array list with given capacity.
-+	 *
-+	 * @param capacity the initial capacity of the array list (may be 0).
-+	 */
-+
-+ public IntArrayList( final int capacity ) {
-+  if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
-+  a = new int[ capacity ];
-+ }
-+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
-+	 */
-+ public IntArrayList() {
-+  this( DEFAULT_INITIAL_CAPACITY );
-+ }
-+ /** Creates a new array list and fills it with a given collection.
-+	 *
-+	 * @param c a collection that will be used to fill the array list.
-+	 */
-+ public IntArrayList( final Collection<? extends Integer> c ) {
-+  this( c.size() );
-+  size = IntIterators.unwrap( IntIterators.asIntIterator( c.iterator() ), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection that will be used to fill the array list.
-+	 */
-+ public IntArrayList( final IntCollection c ) {
-+  this( c.size() );
-+  size = IntIterators.unwrap( c.iterator(), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific list.
-+	 *
-+	 * @param l a type-specific list that will be used to fill the array list.
-+	 */
-+ public IntArrayList( final IntList l ) {
-+  this( l.size() );
-+  l.getElements( 0, a, 0, size = l.size() );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 */
-+ public IntArrayList( final int a[] ) {
-+  this( a, 0, a.length );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 */
-+ public IntArrayList( final int a[], final int offset, final int length ) {
-+  this( length );
-+  System.arraycopy( a, offset, this.a, 0, length );
-+  size = length;
-+ }
-+ /** Creates a new array list and fills it with the elements returned by an iterator..
-+	 *
-+	 * @param i an iterator whose returned elements will fill the array list.
-+	 */
-+ public IntArrayList( final Iterator<? extends Integer> i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.next() );
-+ }
-+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
-+	 *
-+	 * @param i a type-specific iterator whose returned elements will fill the array list.
-+	 */
-+ public IntArrayList( final IntIterator i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.nextInt() );
-+ }
-+ /** Returns the backing array of this list.
-+	 *
-+	 * @return the backing array.
-+	 */
-+ public int[] elements() {
-+  return a;
-+ }
-+ /** Wraps a given array into an array list of given size.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @param length the length of the resulting array list.
-+	 * @return a new array list of the given size, wrapping the given array.
-+	 */
-+ public static IntArrayList wrap( final int a[], final int length ) {
-+  if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
-+  final IntArrayList l = new IntArrayList ( a, false );
-+  l.size = length;
-+  return l;
-+ }
-+ /** Wraps a given array into an array list.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @return a new array list wrapping the given array.
-+	 */
-+ public static IntArrayList wrap( final int a[] ) {
-+  return wrap( a, a.length );
-+ }
-+ /** Ensures that this array list can contain the given number of entries without resizing.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+
-+ public void ensureCapacity( final int capacity ) {
-+  a = IntArrays.ensureCapacity( a, capacity, size );
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
-+	 * and in case enlarging it at least by a factor of two.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+
-+ private void grow( final int capacity ) {
-+  a = IntArrays.grow( a, capacity, size );
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public void add( final int index, final int k ) {
-+  ensureIndex( index );
-+  grow( size + 1 );
-+  if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
-+  a[ index ] = k;
-+  size++;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public boolean add( final int k ) {
-+  grow( size + 1 );
-+  a[ size++ ] = k;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public int getInt( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  return a[ index ];
-+ }
-+ public int indexOf( final int k ) {
-+  for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public int lastIndexOf( final int k ) {
-+  for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public int removeInt( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  final int old = a[ index ];
-+  size--;
-+  if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
-+  if ( ASSERTS ) assert size <= a.length;
-+  return old;
-+ }
-+ public boolean rem( final int k ) {
-+  int index = indexOf( k );
-+  if ( index == -1 ) return false;
-+  removeInt( index );
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public int set( final int index, final int k ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  int old = a[ index ];
-+  a[ index ] = k;
-+  return old;
-+ }
-+ public void clear() {
-+  size = 0;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public void size( final int size ) {
-+  if ( size > a.length ) ensureCapacity( size );
-+  if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
-+  this.size = size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Trims this array list so that the capacity is equal to the size. 
-+	 *
-+	 * @see java.util.ArrayList#trimToSize()
-+	 */
-+ public void trim() {
-+  trim( 0 );
-+ }
-+ /** Trims the backing array if it is too large.
-+	 * 
-+	 * If the current array length is smaller than or equal to
-+	 * <code>n</code>, this method does nothing. Otherwise, it trims the
-+	 * array length to the maximum between <code>n</code> and {@link #size()}.
-+	 *
-+	 * <P>This method is useful when reusing lists.  {@linkplain #clear() Clearing a
-+	 * list} leaves the array length untouched. If you are reusing a list
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large array just
-+	 * because of a few large transient lists.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 */
-+
-+ public void trim( final int n ) {
-+  // TODO: use Arrays.trim() and preserve type only if necessary
-+  if ( n >= a.length || size == a.length ) return;
-+  final int t[] = new int[ Math.max( n, size ) ];
-+  System.arraycopy( a, 0, t, 0, size );
-+  a = t;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+    /** Copies element of this type-specific list into the given array using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final int[] a, final int offset, final int length ) {
-+  IntArrays.ensureOffsetLength( a, offset, length );
-+  System.arraycopy( this.a, from, a, offset, length );
-+ }
-+ /** Removes elements of this type-specific list using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
-+  System.arraycopy( a, to, a, from, size - to );
-+  size -= ( to - from );
-+ }
-+ /** Adds elements to this type-specific list using optimized system calls.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( final int index, final int a[], final int offset, final int length ) {
-+  ensureIndex( index );
-+  IntArrays.ensureOffsetLength( a, offset, length );
-+  grow( size + length );
-+  System.arraycopy( this.a, index, this.a, index + length, size - index );
-+  System.arraycopy( a, offset, this.a, index, length );
-+  size += length;
-+ }
-+ public int[] toIntArray( int a[] ) {
-+  if ( a == null || a.length < size ) a = new int[ size ];
-+  System.arraycopy( this.a, 0, a, 0, size );
-+  return a;
-+ }
-+ public boolean addAll( int index, final IntCollection c ) {
-+  ensureIndex( index );
-+  int n = c.size();
-+  if ( n == 0 ) return false;
-+  grow( size + n );
-+  if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
-+  final IntIterator i = c.iterator();
-+  size += n;
-+  while( n-- != 0 ) a[ index++ ] = i.nextInt();
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public boolean addAll( final int index, final IntList l ) {
-+  ensureIndex( index );
-+  final int n = l.size();
-+  if ( n == 0 ) return false;
-+  grow( size + n );
-+  if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
-+  l.getElements( 0, a, index, n );
-+  size += n;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ @Override
-+ public boolean removeAll( final IntCollection c ) {
-+  final int[] a = this.a;
-+  int j = 0;
-+  for( int i = 0; i < size; i++ )
-+   if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
-+  final boolean modified = size != j;
-+  size = j;
-+  return modified;
-+ }
-+ @Override
-+ public boolean removeAll( final Collection<?> c ) {
-+  final int[] a = this.a;
-+  int j = 0;
-+  for( int i = 0; i < size; i++ )
-+   if ( ! c.contains( (Integer.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
-+  final boolean modified = size != j;
-+  size = j;
-+  return modified;
-+ }
-+ public IntListIterator listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractIntListIterator () {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < size; }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
-+    public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( int k ) {
-+     IntArrayList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( int k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     IntArrayList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     IntArrayList.this.removeInt( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public IntArrayList clone() {
-+  IntArrayList c = new IntArrayList ( size );
-+  System.arraycopy( a, 0, c.a, 0, size );
-+  c.size = size;
-+  return c;
-+ }
-+    /** Compares this type-specific array list to another one.
-+	 *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+	 * @param l a type-specific array list.
-+     * @return true if the argument contains the same elements of this type-specific array list.
-+	 */
-+ public boolean equals( final IntArrayList l ) {
-+  if ( l == this ) return true;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  final int[] a1 = a;
-+  final int[] a2 = l.a;
-+  while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
-+  return true;
-+ }
-+    /** Compares this array list to another array list.
-+     *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+     * @param l an array list.
-+     * @return a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     */
-+
-+ public int compareTo( final IntArrayList l ) {
-+  final int s1 = size(), s2 = l.size();
-+  final int a1[] = a, a2[] = l.a;
-+  int e1, e2;
-+  int r, i;
-+  for( i = 0; i < s1 && i < s2; i++ ) {
-+   e1 = a1[ i ];
-+   e2 = a2[ i ];
-+   if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
-+  }
-+  return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
-+ }
-+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
-+ }
-+
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = new int[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based priority queue.
-+ *
-+ * <P>Instances of this class represent a priority queue using a backing
-+ * array&mdash;all operations are performed directly on the array. The array is
-+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
-+ * to reduce its size, if necessary.
-+ *
-+ * <P>This implementation is extremely inefficient, but it is difficult to beat
-+ * when the size of the queue is very small.
-+ */
-+public class IntArrayPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
-+ private static final long serialVersionUID = 1L;
-+ /** The backing array. */
-+
-+ protected transient int array[] = IntArrays.EMPTY_ARRAY;
-+ /** The number of elements in this queue. */
-+ protected int size;
-+ /** The type-specific comparator used in this queue. */
-+ protected IntComparator c;
-+ /** The first index, cached, if {@link #firstIndexValid} is true. */
-+ transient protected int firstIndex;
-+ /** Whether {@link #firstIndex} contains a valid value. */
-+ transient protected boolean firstIndexValid;
-+ /** Creates a new empty queue with a given capacity and comparator.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+
-+ public IntArrayPriorityQueue( int capacity, IntComparator c ) {
-+  if ( capacity > 0 ) this.array = new int[ capacity ];
-+  this.c = c;
-+ }
-+ /** Creates a new empty queue with a given capacity and using the natural order.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public IntArrayPriorityQueue( int capacity ) {
-+  this( capacity, null );
-+ }
-+ /** Creates a new empty queue with a given comparator.
-+	 *
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayPriorityQueue( IntComparator c ) {
-+  this( 0, c );
-+ }
-+ /** Creates a new empty queue using the natural order. 
-+	 */
-+ public IntArrayPriorityQueue() {
-+  this( 0, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayPriorityQueue( final int[] a, int size, final IntComparator c ) {
-+  this( c );
-+  this.array = a;
-+  this.size = size;
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntArrayPriorityQueue( final int[] a, final IntComparator c ) {
-+  this( a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public IntArrayPriorityQueue( final int[] a, int size ) {
-+  this( a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 */
-+ public IntArrayPriorityQueue( final int[] a ) {
-+  this( a, a.length );
-+ }
-+ /** Returns the index of the smallest element. */
-+
-+ private int findFirst() {
-+  if ( firstIndexValid ) return this.firstIndex;
-+  firstIndexValid = true;
-+  int i = size;
-+  int firstIndex = --i;
-+  int first = array[ firstIndex ];
-+  if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
-+  else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
-+  return this.firstIndex = firstIndex;
-+ }
-+ private void ensureNonEmpty() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+ }
-+
-+ public void enqueue( int x ) {
-+  if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
-+  if ( firstIndexValid ) {
-+   if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
-+   else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
-+  }
-+  else firstIndexValid = false;
-+  array[ size++ ] = x;
-+ }
-+ public int dequeueInt() {
-+  ensureNonEmpty();
-+  final int first = findFirst();
-+  final int result = array[ first ];
-+  System.arraycopy( array, first + 1, array, first, --size - first );
-+  firstIndexValid = false;
-+  return result;
-+ }
-+ public int firstInt() {
-+  ensureNonEmpty();
-+  return array[ findFirst() ];
-+ }
-+ public void changed() {
-+  ensureNonEmpty();
-+  firstIndexValid = false;
-+ }
-+ public int size() { return size; }
-+ public void clear() {
-+  size = 0;
-+  firstIndexValid = false;
-+ }
-+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
-+	 */
-+ public void trim() {
-+  array = IntArrays.trim( array, size );
-+ }
-+ public IntComparator comparator() { return c; }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  s.writeInt( array.length );
-+  for( int i = 0; i < size; i++ ) s.writeInt( array[ i ] );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  array = new int[ s.readInt() ];
-+  for( int i = 0; i < size; i++ ) array[ i ] = s.readInt();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2007-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/** A simple, brute-force implementation of a set based on a backing array.
-+ *
-+ * <p>The main purpose of this
-+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very 
-+ * small number of items: just put them into an array and scan linearly to find an item.
-+ */
-+public class IntArraySet extends AbstractIntSet implements java.io.Serializable, Cloneable {
-+ private static final long serialVersionUID = 1L;
-+ /** The backing array (valid up to {@link #size}, excluded). */
-+ private transient int[] a;
-+ /** The number of valid entries in {@link #a}. */
-+ private int size;
-+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
-+	 * 
-+	 * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 */
-+ public IntArraySet( final int[] a ) {
-+  this.a = a;
-+  size = a.length;
-+ }
-+ /** Creates a new empty array set.
-+	 */
-+ public IntArraySet() {
-+  this.a = IntArrays.EMPTY_ARRAY;
-+ }
-+ /** Creates a new empty array set of given initial capacity.
-+	 * 
-+	 * @param capacity the initial capacity.
-+	 */
-+ public IntArraySet( final int capacity ) {
-+  this.a = new int[ capacity ];
-+ }
-+ /** Creates a new array set copying the contents of a given collection.
-+	 * @param c a collection.
-+	 */
-+ public IntArraySet( IntCollection c ) {
-+  this( c.size () );
-+  addAll( c );
-+ }
-+ /** Creates a new array set copying the contents of a given set.
-+	 * @param c a collection.
-+	 */
-+ public IntArraySet( final Collection<? extends Integer> c ) {
-+  this( c.size() );
-+  addAll( c );
-+ }
-+ /** Creates a new array set using the given backing array and the given number of elements of the array.
-+	 *
-+	 * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 * @param size the number of valid elements in <code>a</code>.
-+	 */
-+ public IntArraySet( final int[] a, final int size ) {
-+  this.a = a;
-+  this.size = size;
-+  if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
-+ }
-+ private int findKey( final int o ) {
-+  for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
-+  return -1;
-+ }
-+ @Override
-+
-+ public IntIterator iterator() {
-+  return new AbstractIntIterator () {
-+   int next = 0;
-+   public boolean hasNext() {
-+    return next < size;
-+   }
-+   public int nextInt() {
-+    if ( ! hasNext() ) throw new NoSuchElementException();
-+    return a[ next++ ];
-+   }
-+   public void remove() {
-+    final int tail = size-- - next--;
-+    System.arraycopy( a, next + 1, a, next, tail );
-+   }
-+  };
-+ }
-+ public boolean contains( final int k ) {
-+  return findKey( k ) != -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ @Override
-+ public boolean remove( final int k ) {
-+  final int pos = findKey( k );
-+  if ( pos == -1 ) return false;
-+  final int tail = size - pos - 1;
-+  for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
-+  size--;
-+  return true;
-+ }
-+ @Override
-+ public boolean add( final int k ) {
-+  final int pos = findKey( k );
-+  if ( pos != -1 ) return false;
-+  if ( size == a.length ) {
-+   final int[] b = new int[ size == 0 ? 2 : size * 2 ];
-+   for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
-+   a = b;
-+  }
-+  a[ size++ ] = k;
-+  return true;
-+ }
-+ @Override
-+ public void clear() {
-+  size = 0;
-+ }
-+ @Override
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public IntArraySet clone() {
-+  IntArraySet c;
-+  try {
-+   c = (IntArraySet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.a = a.clone();
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
-+ }
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = new int[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ *
-+ *
-+ *
-+ * For the sorting and binary search code:
-+ *
-+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
-+ *
-+ *   Permission to use, copy, modify, distribute and sell this software and
-+ *   its documentation for any purpose is hereby granted without fee,
-+ *   provided that the above copyright notice appear in all copies and that
-+ *   both that copyright notice and this permission notice appear in
-+ *   supporting documentation. CERN makes no representations about the
-+ *   suitability of this software for any purpose. It is provided "as is"
-+ *   without expressed or implied warranty. 
-+ */
-+package it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Arrays;
-+import it.unimi.dsi.fastutil.Hash;
-+import java.util.Random;
-+import java.util.concurrent.ForkJoinPool;
-+import java.util.concurrent.RecursiveAction;
-+import java.util.concurrent.Callable;
-+import java.util.concurrent.ExecutorCompletionService;
-+import java.util.concurrent.ExecutorService;
-+import java.util.concurrent.Executors;
-+import java.util.concurrent.LinkedBlockingQueue;
-+import java.util.concurrent.atomic.AtomicInteger;
-+/** A class providing static methods and objects that do useful things with type-specific arrays.
-+ *
-+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
-+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
-+ * arrays much like array lists. This can be very useful when efficiency (or
-+ * syntactic simplicity) reasons make array lists unsuitable.
-+ *
-+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
-+ * contain several methods make it possible to load and save arrays of primitive types as sequences
-+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
-+ *
-+ * <h2>Sorting</h2>
-+ *
-+ * <p>There are several sorting methods available. The main theme is that of letting you choose
-+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
-+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
-+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
-+ * to sort an array using the values in another array as comparator.
-+ *
-+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
-+ *
-+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
-+ * on random-looking data. In
-+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
-+ * exploits parallelism better.
-+ *
-+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated), 
-+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
-+ * are about 50% faster than the classical single-pivot implementation used here.
-+ *
-+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
-+ * with your data distribution and on your architecture.
-+ * 
-+ * @see java.util.Arrays
-+ */
-+public class IntArrays {
-+ private IntArrays() {}
-+ /** A static, final, empty array. */
-+ public final static int[] EMPTY_ARRAY = {};
-+ /** Ensures that an array can contain the given number of entries.
-+	 *
-+	 * <P>If you cannot foresee whether this array will need again to be
-+	 * enlarged, you should probably use <code>grow()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>array.length</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static int[] ensureCapacity( final int[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final int t[] =
-+    new int[ length ];
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>preserve</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static int[] ensureCapacity( final int[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final int t[] =
-+    new int[ length ];
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>array.length</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static int[] grow( final int[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final int t[] =
-+    new int[ newLength ];
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length, preserving just a part of the array.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>preserve</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static int[] grow( final int[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final int t[] =
-+    new int[ newLength ];
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Trims the given array to the given length.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new maximum length for the array.
-+	 * @return <code>array</code>, if it contains <code>length</code>
-+	 * entries or less; otherwise, an array with
-+	 * <code>length</code> entries whose entries are the same as
-+	 * the first <code>length</code> entries of <code>array</code>.
-+	 * 
-+	 */
-+ public static int[] trim( final int[] array, final int length ) {
-+  if ( length >= array.length ) return array;
-+  final int t[] =
-+   length == 0 ? EMPTY_ARRAY : new int[ length ];
-+  System.arraycopy( array, 0, t, 0, length );
-+  return t;
-+ }
-+ /** Sets the length of the given array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new length for the array.
-+	 * @return <code>array</code>, if it contains exactly <code>length</code>
-+	 * entries; otherwise, if it contains <em>more</em> than
-+	 * <code>length</code> entries, an array with <code>length</code> entries
-+	 * whose entries are the same as the first <code>length</code> entries of
-+	 * <code>array</code>; otherwise, an array with <code>length</code> entries
-+	 * whose first <code>array.length</code> entries are the same as those of
-+	 * <code>array</code>.
-+	 * 
-+	 */
-+ public static int[] setLength( final int[] array, final int length ) {
-+  if ( length == array.length ) return array;
-+  if ( length < array.length ) return trim( array, length );
-+  return ensureCapacity( array, length );
-+ }
-+ /** Returns a copy of a portion of an array.
-+	 *
-+	 * @param array an array.
-+	 * @param offset the first element to copy.
-+	 * @param length the number of elements to copy.
-+	 * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
-+	 */
-+ public static int[] copy( final int[] array, final int offset, final int length ) {
-+  ensureOffsetLength( array, offset, length );
-+  final int[] a =
-+   length == 0 ? EMPTY_ARRAY : new int[ length ];
-+  System.arraycopy( array, offset, a, 0, length );
-+  return a;
-+ }
-+ /** Returns a copy of an array.
-+	 *
-+	 * @param array an array.
-+	 * @return a copy of <code>array</code>.
-+	 */
-+ public static int[] copy( final int[] array ) {
-+  return array.clone();
-+ }
-+ /** Fills the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param value the new value for all elements of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static void fill( final int[] array, final int value ) {
-+  int i = array.length;
-+  while( i-- != 0 ) array[ i ] = value;
-+ }
-+ /** Fills a portion of the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param from the starting index of the portion to fill (inclusive).
-+	 * @param to the end index of the portion to fill (exclusive).
-+	 * @param value the new value for all elements of the specified portion of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static void fill( final int[] array, final int from, int to, final int value ) {
-+  ensureFromTo( array, from, to );
-+  if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
-+  else for( int i = from; i < to; i++ ) array[ i ] = value;
-+ }
-+ /** Returns true if the two arrays are elementwise equal.
-+	 *
-+	 * @param a1 an array.
-+	 * @param a2 another array.
-+	 * @return true if the two arrays are of the same length, and their elements are equal.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
-+	 */
-+ @Deprecated
-+ public static boolean equals( final int[] a1, final int a2[] ) {
-+  int i = a1.length;
-+  if ( i != a2.length ) return false;
-+  while( i-- != 0 ) if (! ( (a1[ i ]) == (a2[ i ]) ) ) return false;
-+  return true;
-+ }
-+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param from a start index (inclusive).
-+	 * @param to an end index (exclusive).
-+	 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
-+	 */
-+ public static void ensureFromTo( final int[] a, final int from, final int to ) {
-+  Arrays.ensureFromTo( a.length, from, to );
-+ }
-+ /** Ensures that a range given by an offset and a length fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param offset a start index.
-+	 * @param length a length (the number of elements in the range).
-+	 * @throws IllegalArgumentException if <code>length</code> is negative.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
-+	 */
-+ public static void ensureOffsetLength( final int[] a, final int offset, final int length ) {
-+  Arrays.ensureOffsetLength( a.length, offset, length );
-+ }
-+ /** Ensures that two arrays are of the same length.
-+	 *
-+	 * @param a an array.
-+	 * @param b another array.
-+	 * @throws IllegalArgumentException if the two argument arrays are not of the same length.
-+	 */
-+ public static void ensureSameLength( final int[] a, final int[] b ) {
-+  if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
-+ }
-+ private static final int QUICKSORT_NO_REC = 16;
-+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
-+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
-+ private static final int MERGESORT_NO_REC = 16;
-+ /** Swaps two elements of an anrray.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 */
-+ public static void swap( final int x[], final int a, final int b ) {
-+  final int t = x[ a ];
-+  x[ a ] = x[ b ];
-+  x[ b ] = t;
-+ }
-+ /** Swaps two sequences of elements of an array.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 * @param n the number of elements to exchange starting at {@code a} and {@code b}.
-+	 */
-+ public static void swap( final int[] x, int a, int b, final int n ) {
-+  for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
-+ }
-+ private static int med3( final int x[], final int a, final int b, final int c, IntComparator comp ) {
-+  final int ab = comp.compare( x[ a ], x[ b ] );
-+  final int ac = comp.compare( x[ a ], x[ c ] );
-+  final int bc = comp.compare( x[ b ], x[ c ] );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static void selectionSort( final int[] a, final int from, final int to, final IntComparator comp ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
-+   if ( m != i ) {
-+    final int u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+ private static void insertionSort( final int[] a, final int from, final int to, final IntComparator comp ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = a[ i ];
-+   int j = i;
-+   for ( int u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static void quickSort( final int[] x, final int from, final int to, final IntComparator comp ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to, comp );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s, comp );
-+   m = med3( x, m - s, m, m + s, comp );
-+   n = med3( x, n - 2 * s, n - s, n, comp );
-+  }
-+  m = med3( x, l, m, n, comp ); // Mid-size, med of 3
-+  final int v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while( true ) {
-+   int comparison;
-+   while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static void quickSort( final int[] x, final IntComparator comp ) {
-+  quickSort( x, 0, x.length, comp );
-+ }
-+ protected static class ForkJoinQuickSortComp extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] x;
-+  private final IntComparator comp;
-+  public ForkJoinQuickSortComp( final int[] x , final int from , final int to, final IntComparator comp ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.comp = comp;
-+  }
-+  @Override
-+  protected void compute() {
-+   final int[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to, comp );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final int v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ), new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ) );
-+   else invokeAll( new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void parallelQuickSort( final int[] x, final int from, final int to, final IntComparator comp ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortComp ( x, from, to, comp ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void parallelQuickSort( final int[] x, final IntComparator comp ) {
-+  parallelQuickSort( x, 0, x.length, comp );
-+ }
-+
-+ private static int med3( final int x[], final int a, final int b, final int c ) {
-+  final int ab = ( Integer.compare((x[ a ]),(x[ b ])) );
-+  final int ac = ( Integer.compare((x[ a ]),(x[ c ])) );
-+  final int bc = ( Integer.compare((x[ b ]),(x[ c ])) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+
-+ private static void selectionSort( final int[] a, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( ( (a[ j ]) < (a[ m ]) ) ) m = j;
-+   if ( m != i ) {
-+    final int u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+
-+ private static void insertionSort( final int[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = a[ i ];
-+   int j = i;
-+   for ( int u = a[ j - 1 ]; ( (t) < (u) ); u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSort( final int[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, l, m, n ); // Mid-size, med of 3
-+  final int v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( Integer.compare((x[ b ]),(v)) ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( Integer.compare((x[ c ]),(v)) ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void quickSort( final int[] x ) {
-+  quickSort( x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] x;
-+  public ForkJoinQuickSort( final int[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final int[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final int v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( Integer.compare((x[ b ]),(v)) ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( Integer.compare((x[ c ]),(v)) ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ), new ForkJoinQuickSort ( x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort ( x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSort( final int[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSort ( x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void parallelQuickSort( final int[] x ) {
-+  parallelQuickSort( x, 0, x.length );
-+ }
-+
-+ private static int med3Indirect( final int perm[], final int x[], final int a, final int b, final int c ) {
-+  final int aa = x[ perm[ a ] ];
-+  final int bb = x[ perm[ b ] ];
-+  final int cc = x[ perm[ c ] ];
-+  final int ab = ( Integer.compare((aa),(bb)) );
-+  final int ac = ( Integer.compare((aa),(cc)) );
-+  final int bc = ( Integer.compare((bb),(cc)) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+
-+ private static void insertionSortIndirect( final int[] perm, final int[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = perm[ i ];
-+   int j = i;
-+   for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ); u = perm[ --j - 1 ] ) {
-+    perm[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   perm[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSortIndirect( final int[] perm, final int[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   insertionSortIndirect( perm, x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+  }
-+  m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
-+  final int v = x[ perm[ m ] ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( Integer.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( Integer.compare((x[ perm[ c ] ]),(v)) ) ) >=0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   IntArrays.swap( perm, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  IntArrays.swap( perm, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  IntArrays.swap( perm, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 */
-+ public static void quickSortIndirect( final int perm[], final int[] x ) {
-+  quickSortIndirect( perm, x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSortIndirect extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] perm;
-+  private final int[] x;
-+  public ForkJoinQuickSortIndirect( final int perm[], final int[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.perm = perm;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final int[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSortIndirect( perm, x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+   m = med3Indirect( perm, x, l, m, n );
-+   final int v = x[ perm[ m ] ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( Integer.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( Integer.compare((x[ perm[ c ] ]),(v)) ) ) >= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    IntArrays.swap( perm, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   IntArrays.swap( perm, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   IntArrays.swap( perm, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ), new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSortIndirect( final int[] perm, final int[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortIndirect ( perm, x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void parallelQuickSortIndirect( final int perm[], final int[] x ) {
-+  parallelQuickSortIndirect( perm, x, 0, x.length );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 * @param from the index of the first element (inclusive) to be stabilized.
-+	 * @param to the index of the last element (exclusive) to be stabilized.
-+	 */
-+ public static void stabilize( final int perm[], final int[] x, final int from, final int to ) {
-+  int curr = from;
-+  for( int i = from + 1; i < to; i++ ) {
-+   if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
-+    if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
-+    curr = i;
-+   }
-+  }
-+  if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 */
-+ public static void stabilize( final int perm[], final int[] x ) {
-+  stabilize( perm, x, 0, perm.length );
-+ }
-+
-+ private static int med3( final int x[], final int[] y, final int a, final int b, final int c ) {
-+  int t;
-+  final int ab = ( t = ( Integer.compare((x[ a ]),(x[ b ])) ) ) == 0 ? ( Integer.compare((y[ a ]),(y[ b ])) ) : t;
-+  final int ac = ( t = ( Integer.compare((x[ a ]),(x[ c ])) ) ) == 0 ? ( Integer.compare((y[ a ]),(y[ c ])) ) : t;
-+  final int bc = ( t = ( Integer.compare((x[ b ]),(x[ c ])) ) ) == 0 ? ( Integer.compare((y[ b ]),(y[ c ])) ) : t;
-+  return ( ab < 0 ?
-+    ( bc < 0 ? b : ac < 0 ? c : a ) :
-+    ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static void swap( final int x[], final int[] y, final int a, final int b ) {
-+  final int t = x[ a ];
-+  final int u = y[ a ];
-+  x[ a ] = x[ b ];
-+  y[ a ] = y[ b ];
-+  x[ b ] = t;
-+  y[ b ] = u;
-+ }
-+ private static void swap( final int[] x, final int[] y, int a, int b, final int n ) {
-+  for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
-+ }
-+
-+ private static void selectionSort( final int[] a, final int[] b, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i, u;
-+   for( int j = i + 1; j < to; j++ )
-+    if ( ( u = ( Integer.compare((a[ j ]),(a[ m ])) ) ) < 0 || u == 0 && ( (b[ j ]) < (b[ m ]) ) ) m = j;
-+   if ( m != i ) {
-+    int t = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = t;
-+    t = b[ i ];
-+    b[ i ] = b[ m ];
-+    b[ m ] = t;
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSort( final int[] x, final int[] y, final int from, final int to ) {
-+  final int len = to - from;
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, y, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, y, l, m, n ); // Mid-size, med of 3
-+  final int v = x[ m ], w = y[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while ( true ) {
-+   int comparison, t;
-+   while ( b <= c && ( comparison = ( t = ( Integer.compare((x[ b ]),(v)) ) ) == 0 ? ( Integer.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = ( t = ( Integer.compare((x[ c ]),(v)) ) ) == 0 ? ( Integer.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, y, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, y, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, y, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
-+ }
-+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static void quickSort( final int[] x, final int[] y ) {
-+  ensureSameLength( x, y );
-+  quickSort( x, y, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort2 extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] x, y;
-+  public ForkJoinQuickSort2( final int[] x, final int[] y, final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.y = y;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final int[] x = this.x;
-+   final int[] y = this.y;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, y, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+   m = med3( x, y, l, m, n );
-+   final int v = x[ m ], w = y[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison, t;
-+    while ( b <= c && ( comparison = ( t = ( Integer.compare((x[ b ]),(v)) ) ) == 0 ? ( Integer.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( t = ( Integer.compare((x[ c ]),(v)) ) ) == 0 ? ( Integer.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, y, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, y, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, y, b, to - s, s );
-+   s = b - a;
-+   t = d - c;
-+   // Recursively sort non-partition-elements
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ), new ForkJoinQuickSort2 ( x, y, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort2 ( x, y, to - t, to ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSort( final int[] x, final int[] y, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
-+  final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+  pool.invoke( new ForkJoinQuickSort2 ( x, y, from, to ) );
-+  pool.shutdown();
-+ }
-+ /** Sorts two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static void parallelQuickSort( final int[] x, final int[] y ) {
-+  ensureSameLength( x, y );
-+  parallelQuickSort( x, y, 0, x.length );
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated. 
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+
-+ public static void mergeSort( final int a[], final int from, final int to, final int supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to );
-+   return;
-+  }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, a );
-+  mergeSort( supp, mid, to, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( ( (supp[ mid - 1 ]) <= (supp[ mid ]) ) ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && ( (supp[ p ]) <= (supp[ q ]) ) ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void mergeSort( final int a[], final int from, final int to ) {
-+  mergeSort( a, from, to, a.clone() );
-+ }
-+ /**	Sorts an array according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void mergeSort( final int a[] ) {
-+  mergeSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+ public static void mergeSort( final int a[], final int from, final int to, IntComparator comp, final int supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to, comp );
-+   return;
-+     }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, comp, a );
-+  mergeSort( supp, mid, to, comp, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 *
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void mergeSort( final int a[], final int from, final int to, IntComparator comp ) {
-+  mergeSort( a, from, to, comp, a.clone() );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort.  An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void mergeSort( final int a[], IntComparator comp ) {
-+  mergeSort( a, 0, a.length, comp );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+
-+ public static int binarySearch( final int[] a, int from, int to, final int key ) {
-+  int midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   if (midVal < key) from = mid + 1;
-+   else if (midVal > key) to = mid - 1;
-+   else return mid;
-+        }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final int[] a, final int key ) {
-+  return binarySearch( a, 0, a.length, key );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final int[] a, int from, int to, final int key, final IntComparator c ) {
-+  int midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   final int cmp = c.compare( midVal, key );
-+   if ( cmp < 0 ) from = mid + 1;
-+   else if (cmp > 0) to = mid - 1;
-+   else return mid; // key found
-+  }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final int[] a, final int key, final IntComparator c ) {
-+  return binarySearch( a, 0, a.length, key, c );
-+ }
-+ /** The size of a digit used during radix sort (must be a power of 2). */
-+ private static final int DIGIT_BITS = 8;
-+ /** The mask to extract a digit of {@link #DIGIT_BITS} bits. */
-+ private static final int DIGIT_MASK = ( 1 << DIGIT_BITS ) - 1;
-+ /** The number of digits per element. */
-+ private static final int DIGITS_PER_ELEMENT = Integer.SIZE / DIGIT_BITS;
-+ private static final int RADIXSORT_NO_REC = 1024;
-+ private static final int PARALLEL_RADIXSORT_NO_FORK = 1024;
-+ /** This method fixes negative numbers so that the combination exponent/significand is lexicographically sorted. */
-+ /** Sorts the specified array using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation is significantly faster than quicksort 
-+	 * already at small sizes (say, more than 10000 elements), but it can only
-+	 * sort in ascending order. 
-+	 * 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void radixSort( final int[] a ) {
-+  radixSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified range of an array using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation is significantly faster than quicksort 
-+	 * already at small sizes (say, more than 10000 elements), but it can only
-+	 * sort in ascending order. 
-+	 * 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final int[] a, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   quickSort( a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ ((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    int t = a[ i ];
-+    c = ((t) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while ( ( d = --pos[ c ] ) > i ) {
-+      final int z = t;
-+      t = a[ d ];
-+      a[ d ] = z;
-+      c = ((t) >>> shift & DIGIT_MASK ^ signMask);
-+     }
-+     a[ i ] = t;
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) quickSort( a, i, i + count[ c ] );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ protected final static class Segment {
-+  protected final int offset, length, level;
-+  protected Segment( final int offset, final int length, final int level ) {
-+   this.offset = offset;
-+   this.length = length;
-+   this.level = level;
-+  }
-+  @Override
-+  public String toString() {
-+   return "Segment [offset=" + offset + ", length=" + length + ", level=" + level + "]";
-+  }
-+ }
-+ protected final static Segment POISON_PILL = new Segment( -1, -1, -1 );
-+ /** Sorts the specified range of an array using parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelRadixSort( final int[] a, final int from, final int to ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   quickSort( a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
-+   public Void call() throws Exception {
-+    final int[] count = new int[ 1 << DIGIT_BITS ];
-+    final int[] pos = new int[ 1 << DIGIT_BITS ];
-+    for(;;) {
-+     if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
-+     final Segment segment = queue.take();
-+     if ( segment == POISON_PILL ) return null;
-+     final int first = segment.offset;
-+     final int length = segment.length;
-+     final int level = segment.level;
-+     final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+     final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+     // Count keys.
-+     for( int i = first + length; i-- != first; ) count[ ((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+     // Compute cumulative distribution
-+     int lastUsed = -1;
-+     for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+      if ( count[ i ] != 0 ) lastUsed = i;
-+      pos[ i ] = ( p += count[ i ] );
-+     }
-+     final int end = first + length - count[ lastUsed ];
-+     // i moves through the start of each block
-+     for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+      int t = a[ i ];
-+      c = ((t) >>> shift & DIGIT_MASK ^ signMask);
-+      if ( i < end ) {
-+       while( ( d = --pos[ c ] ) > i ) {
-+        final int z = t;
-+        t = a[ d ];
-+        a[ d ] = z;
-+        c = ((t) >>> shift & DIGIT_MASK ^ signMask);
-+       }
-+       a[ i ] = t;
-+      }
-+      if ( level < maxLevel && count[ c ] > 1 ) {
-+       if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, i, i + count[ c ] );
-+       else {
-+        queueSize.incrementAndGet();
-+        queue.add( new Segment( i, count[ c ], level + 1 ) );
-+       }
-+      }
-+     }
-+     queueSize.decrementAndGet();
-+    }
-+   }
-+  } );
-+  Throwable problem = null;
-+  for( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts the specified array using parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void parallelRadixSort( final int[] a ) {
-+  parallelRadixSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified array using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final int[] a, final boolean stable ) {
-+  radixSortIndirect( perm, a, 0, perm.length, stable );
-+ }
-+ /** Sorts the specified array using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
-+	 * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final int[] a, final int from, final int to, final boolean stable ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   insertionSortIndirect( perm, a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   if ( stable ) {
-+    for( int i = first + length; i-- != first; ) support[ --pos[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+    System.arraycopy( support, 0, perm, first, length );
-+    for( int i = 0, p = first; i <= lastUsed; i++ ) {
-+     if ( level < maxLevel && count[ i ] > 1 ) {
-+      if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, p, p + count[ i ] );
-+      else {
-+       offsetStack[ stackPos ] = p;
-+       lengthStack[ stackPos ] = count[ i ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+     p += count[ i ];
-+    }
-+    java.util.Arrays.fill( count, 0 );
-+   }
-+   else {
-+    final int end = first + length - count[ lastUsed ];
-+    // i moves through the start of each block
-+    for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+     int t = perm[ i ];
-+     c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+     if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+      while( ( d = --pos[ c ] ) > i ) {
-+       final int z = t;
-+       t = perm[ d ];
-+       perm[ d ] = z;
-+       c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+      }
-+      perm[ i ] = t;
-+     }
-+     if ( level < maxLevel && count[ c ] > 1 ) {
-+      if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, i, i + count[ c ] );
-+      else {
-+       offsetStack[ stackPos ] = i;
-+       lengthStack[ stackPos ] = count[ c ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of an array using parallel indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void parallelRadixSortIndirect( final int perm[], final int[] a, final int from, final int to, final boolean stable ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   radixSortIndirect( perm, a, from, to, stable );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
-+   public Void call() throws Exception {
-+    final int[] count = new int[ 1 << DIGIT_BITS ];
-+    final int[] pos = new int[ 1 << DIGIT_BITS ];
-+    for(;;) {
-+     if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
-+     final Segment segment = queue.take();
-+     if ( segment == POISON_PILL ) return null;
-+     final int first = segment.offset;
-+     final int length = segment.length;
-+     final int level = segment.level;
-+     final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+     final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+     // Count keys.
-+     for( int i = first + length; i-- != first; ) count[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+     // Compute cumulative distribution
-+     int lastUsed = -1;
-+     for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+      if ( count[ i ] != 0 ) lastUsed = i;
-+      pos[ i ] = ( p += count[ i ] );
-+     }
-+     if ( stable ) {
-+      for( int i = first + length; i-- != first; ) support[ --pos[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+      System.arraycopy( support, first, perm, first, length );
-+      for( int i = 0, p = first; i <= lastUsed; i++ ) {
-+       if ( level < maxLevel && count[ i ] > 1 ) {
-+        if ( count[ i ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, p, p + count[ i ], stable );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( p, count[ i ], level + 1 ) );
-+        }
-+       }
-+       p += count[ i ];
-+      }
-+      java.util.Arrays.fill( count, 0 );
-+     }
-+     else {
-+      final int end = first + length - count[ lastUsed ];
-+      // i moves through the start of each block
-+      for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+       int t = perm[ i ];
-+       c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+       if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+        while( ( d = --pos[ c ] ) > i ) {
-+         final int z = t;
-+         t = perm[ d ];
-+         perm[ d ] = z;
-+         c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+        }
-+        perm[ i ] = t;
-+       }
-+       if ( level < maxLevel && count[ c ] > 1 ) {
-+        if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, i, i + count[ c ], stable );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( i, count[ c ], level + 1 ) );
-+        }
-+       }
-+      }
-+     }
-+     queueSize.decrementAndGet();
-+    }
-+   }
-+  } );
-+  Throwable problem = null;
-+  for( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts the specified array using parallel indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void parallelRadixSortIndirect( final int perm[], final int[] a, final boolean stable ) {
-+  parallelRadixSortIndirect( perm, a, 0, a.length, stable );
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using radix sort.
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 */
-+ public static void radixSort( final int[] a, final int[] b ) {
-+  ensureSameLength( a, b );
-+  radixSort( a, b, 0, a.length );
-+ }
-+ /** Sorts the specified range of elements of two arrays using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final int[] a, final int[] b, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   selectionSort( a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    int t = a[ i ];
-+    int u = b[ i ];
-+    c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while( ( d = --pos[ c ] ) > i ) {
-+      c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+      int z = t;
-+      t = a[ d ];
-+      a[ d ] = z;
-+      z = u;
-+      u = b[ d ];
-+      b[ d ] = z;
-+     }
-+     a[ i ] = t;
-+     b[ i ] = u;
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, b, i, i + count[ c ] );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays using a parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelRadixSort( final int[] a, final int[] b, final int from, final int to ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   quickSort( a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch." );
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  for ( int i = numberOfThreads; i-- != 0; )
-+   executorCompletionService.submit( new Callable<Void>() {
-+    public Void call() throws Exception {
-+     final int[] count = new int[ 1 << DIGIT_BITS ];
-+     final int[] pos = new int[ 1 << DIGIT_BITS ];
-+     for ( ;; ) {
-+      if ( queueSize.get() == 0 ) for ( int i = numberOfThreads; i-- != 0; )
-+       queue.add( POISON_PILL );
-+      final Segment segment = queue.take();
-+      if ( segment == POISON_PILL ) return null;
-+      final int first = segment.offset;
-+      final int length = segment.length;
-+      final int level = segment.level;
-+      final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+      final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+      final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS;
-+      // Count keys.
-+      for ( int i = first + length; i-- != first; )
-+       count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+      // Compute cumulative distribution
-+      int lastUsed = -1;
-+      for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+       if ( count[ i ] != 0 ) lastUsed = i;
-+       pos[ i ] = ( p += count[ i ] );
-+      }
-+      final int end = first + length - count[ lastUsed ];
-+      for ( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+       int t = a[ i ];
-+       int u = b[ i ];
-+       c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+       if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+        while ( ( d = --pos[ c ] ) > i ) {
-+         c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+         final int z = t;
-+         final int w = u;
-+         t = a[ d ];
-+         u = b[ d ];
-+         a[ d ] = z;
-+         b[ d ] = w;
-+        }
-+        a[ i ] = t;
-+        b[ i ] = u;
-+       }
-+       if ( level < maxLevel && count[ c ] > 1 ) {
-+        if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, b, i, i + count[ c ] );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( i, count[ c ], level + 1 ) );
-+        }
-+       }
-+      }
-+      queueSize.decrementAndGet();
-+     }
-+    }
-+   } );
-+  Throwable problem = null;
-+  for ( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch ( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts two arrays using a parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 */
-+ public static void parallelRadixSort( final int[] a, final int[] b ) {
-+  ensureSameLength( a, b );
-+  parallelRadixSort( a, b, 0, a.length );
-+ }
-+ private static void insertionSortIndirect( final int[] perm, final int[] a, final int[] b, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = perm[ i ];
-+   int j = i;
-+   for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ) || ( (a[ t ]) == (a[ u ]) ) && ( (b[ t ]) < (b[ u ]) ); u = perm[ --j - 1 ] ) {
-+    perm[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   perm[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final int[] a, final int[] b, final boolean stable ) {
-+  ensureSameLength( a, b );
-+  radixSortIndirect( perm, a, b, 0, a.length, stable );
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
-+	 * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final int[] a, final int[] b, final int from, final int to, final boolean stable ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   insertionSortIndirect( perm, a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ ((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   if ( stable ) {
-+    for( int i = first + length; i-- != first; ) support[ --pos[ ((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+    System.arraycopy( support, 0, perm, first, length );
-+    for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+     if ( level < maxLevel && count[ i ] > 1 ) {
-+      if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, p, p + count[ i ] );
-+      else {
-+       offsetStack[ stackPos ] = p;
-+       lengthStack[ stackPos ] = count[ i ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+     p += count[ i ];
-+    }
-+    java.util.Arrays.fill( count, 0 );
-+   }
-+   else {
-+    final int end = first + length - count[ lastUsed ];
-+    // i moves through the start of each block
-+    for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+     int t = perm[ i ];
-+     c = ((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+     if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+      while( ( d = --pos[ c ] ) > i ) {
-+       final int z = t;
-+       t = perm[ d ];
-+       perm[ d ] = z;
-+       c = ((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+      }
-+      perm[ i ] = t;
-+     }
-+     if ( level < maxLevel && count[ c ] > 1 ) {
-+      if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, i, i + count[ c ] );
-+      else {
-+       offsetStack[ stackPos ] = i;
-+       lengthStack[ stackPos ] = count[ c ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+    }
-+   }
-+  }
-+ }
-+ private static void selectionSort( final int[][] a, final int from, final int to, final int level ) {
-+  final int layers = a.length;
-+  final int firstLayer = level / DIGITS_PER_ELEMENT;
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) {
-+    for( int p = firstLayer; p < layers; p++ ) {
-+     if ( a[ p ][ j ] < a[ p ][ m ] ) {
-+      m = j;
-+      break;
-+     }
-+     else if ( a[ p ][ j ] > a[ p ][ m ] ) break;
-+    }
-+   }
-+   if ( m != i ) {
-+    for( int p = layers; p-- != 0; ) {
-+     final int u = a[ p ][ i ];
-+     a[ p ][ i ] = a[ p ][ m ];
-+     a[ p ][ m ] = u;
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified array of arrays lexicographically using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
-+	 * in the same position will be considered a single key, and permuted
-+	 * accordingly.
-+	 *
-+	 * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
-+	 */
-+ public static void radixSort( final int[][] a ) {
-+  radixSort( a, 0, a[ 0 ].length );
-+ }
-+ /** Sorts the specified array of arrays lexicographically using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
-+	 * in the same position will be considered a single key, and permuted
-+	 * accordingly.
-+	 *
-+	 * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final int[][] a, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   selectionSort( a, from, to, 0 );
-+   return;
-+  }
-+  final int layers = a.length;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  for( int p = layers, l = a[ 0 ].length; p-- != 0; ) if ( a[ p ].length != l ) throw new IllegalArgumentException( "The array of index " + p + " has not the same length of the array of index 0." );
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final int[] t = new int[ layers ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int[] k = a[ level / DIGITS_PER_ELEMENT ]; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    for( int p = layers; p-- != 0; ) t[ p ] = a[ p ][ i ];
-+    c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while( ( d = --pos[ c ] ) > i ) {
-+      c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+      for( int p = layers; p-- != 0; ) {
-+       final int u = t[ p ];
-+       t[ p ] = a[ p ][ d ];
-+       a[ p ][ d ] = u;
-+      }
-+     }
-+     for( int p = layers; p-- != 0; ) a[ p ][ i ] = t[ p ];
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, i, i + count[ c ], level + 1 );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param from the index of the first element (inclusive) to be shuffled.
-+	 * @param to the index of the last element (exclusive) to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static int[] shuffle( final int[] a, final int from, final int to, final Random random ) {
-+  for( int i = to - from; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final int t = a[ from + i ];
-+   a[ from + i ] = a[ from + p ];
-+   a[ from + p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Shuffles the specified array using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static int[] shuffle( final int[] a, final Random random ) {
-+  for( int i = a.length; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final int t = a[ i ];
-+   a[ i ] = a[ p ];
-+   a[ p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static int[] reverse( final int[] a ) {
-+  final int length = a.length;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final int t = a[ length - i - 1 ];
-+   a[ length - i - 1 ] = a[ i ];
-+   a[ i ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array fragment.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @param from the index of the first element (inclusive) to be reversed.
-+	 * @param to the index of the last element (exclusive) to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static int[] reverse( final int[] a, final int from, final int to ) {
-+  final int length = to - from;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final int t = a[ from + length - i - 1 ];
-+   a[ from + length - i - 1 ] = a[ from + i ];
-+   a[ from + i ] = t;
-+  }
-+  return a;
-+ }
-+ /** A type-specific content-based hash strategy for arrays. */
-+ private static final class ArrayHashStrategy implements Hash.Strategy<int[]>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  public int hashCode( final int[] o ) {
-+   return java.util.Arrays.hashCode( o );
-+  }
-+  public boolean equals( final int[] a, final int[] b ) {
-+   return java.util.Arrays.equals( a, b );
-+  }
-+ }
-+ /** A type-specific content-based hash strategy for arrays.
-+	 *
-+	 * <P>This hash strategy may be used in custom hash collections whenever keys are
-+	 * arrays, and they must be considered equal by content. This strategy
-+	 * will handle <code>null</code> correctly, and it is serializable.
-+	 */
-+ public final static Hash.Strategy<int[]> HASH_STRATEGY = new ArrayHashStrategy();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.BidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
-+ * and the possibility to skip elements backwards.
-+ *
-+ * @see BidirectionalIterator
-+ */
-+public interface IntBidirectionalIterator extends IntIterator , ObjectBidirectionalIterator<Integer> {
-+ /**
-+	 * Returns the previous element as a primitive type.
-+	 *
-+	 * @return the previous element in the iteration.
-+	 * @see java.util.ListIterator#previous()
-+	 */
-+ int previousInt();
-+ /** Moves back for the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #previous()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasPrevious()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip back.
-+	 * @return the number of elements actually skipped.
-+	 * @see java.util.Iterator#next()
-+	 */
-+ int back( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Collection;
-+/** A type-specific {@link Collection}; provides some additional methods
-+ * that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
-+ * a slightly different semantics for {@link #toArray(Object[])}.
-+ *
-+ * @see Collection
-+ */
-+public interface IntCollection extends Collection<Integer>, IntIterable {
-+ /** Returns a type-specific iterator on the elements of this collection.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in 
-+	 * {@link java.lang.Iterable#iterator()}, which was already 
-+	 * strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Collection}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this collection.
-+	 */
-+ IntIterator iterator();
-+ /** Returns a type-specific iterator on this elements of this collection.
-+	 *
-+	 * @see #iterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ IntIterator intIterator();
-+ /** Returns an containing the items of this collection;
-+	 * the runtime type of the returned array is that of the specified array. 
-+	 *
-+	 * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ <T> T[] toArray(T[] a);
-+ /**
-+	 * @see Collection#contains(Object)
-+	 */
-+ boolean contains( int key );
-+ /** Returns a primitive type array containing the items of this collection. 
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray()
-+	 */
-+ int[] toIntArray();
-+ /** Returns a primitive type array containing the items of this collection.
-+	 *
-+	 * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ int[] toIntArray( int a[] );
-+ /** Returns a primitive type array containing the items of this collection. 
-+	 *
-+	 * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ int[] toArray( int a[] );
-+ /**
-+	 * @see Collection#add(Object)
-+	 */
-+ boolean add( int key );
-+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
-+	 * with the similarly named index-based method in the {@link java.util.List} interface
-+	 * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
-+	 * <code>remove()</code>.
-+	 *
-+	 * @see Collection#remove(Object)
-+	 */
-+ boolean rem( int key );
-+ /**
-+	 * @see Collection#addAll(Collection)
-+	 */
-+ boolean addAll( IntCollection c );
-+ /**
-+	 * @see Collection#containsAll(Collection)
-+	 */
-+ boolean containsAll( IntCollection c );
-+ /**
-+	 * @see Collection#removeAll(Collection)
-+	 */
-+ boolean removeAll( IntCollection c );
-+ /**
-+	 * @see Collection#retainAll(Collection)
-+	 */
-+ boolean retainAll( IntCollection c );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Collection;
-+import it.unimi.dsi.fastutil.objects.ObjectArrays;
-+/** A class providing static methods and objects that do useful things with type-specific collections.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class IntCollections {
-+ private IntCollections() {}
-+ /** An immutable class representing an empty type-specific collection.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific collection.
-+	 */
-+ public abstract static class EmptyCollection extends AbstractIntCollection {
-+  protected EmptyCollection() {}
-+  public boolean add( int k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( int k ) { return false; }
-+  public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
-+  public int[] toIntArray( int[] a ) { return a; }
-+  public int[] toIntArray() { return IntArrays.EMPTY_ARRAY; }
-+  public boolean rem( int k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( IntCollection c ) { return c.isEmpty(); }
-+ 
-+  public IntBidirectionalIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
-+  public int size() { return 0; }
-+  public void clear() {}
-+  public int hashCode() { return 0; }
-+  public boolean equals( Object o ) {
-+   if ( o == this ) return true;
-+   if ( ! ( o instanceof Collection ) ) return false;
-+   return ((Collection<?>)o).isEmpty();
-+  }
-+ }
-+ /** A synchronized wrapper class for collections. */
-+ public static class SynchronizedCollection implements IntCollection , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntCollection collection;
-+  protected final Object sync;
-+  protected SynchronizedCollection( final IntCollection c, final Object sync ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedCollection( final IntCollection c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = this;
-+  }
-+  public int size() { synchronized( sync ) { return collection.size(); } }
-+  public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
-+  public boolean contains( final int o ) { synchronized( sync ) { return collection.contains( o ); } }
-+  public int[] toIntArray() { synchronized( sync ) { return collection.toIntArray(); } }
-+  public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
-+  public int[] toIntArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
-+  public int[] toArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
-+  public boolean addAll( final IntCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
-+  public boolean containsAll( final IntCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
-+  public boolean removeAll( final IntCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
-+  public boolean retainAll( final IntCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
-+  public boolean add( final Integer k ) { synchronized( sync ) { return collection.add( k ); } }
-+  public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
-+  public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
-+  public IntIterator iterator() { return collection.iterator(); }
-+  @Deprecated
-+  public IntIterator intIterator() { return iterator(); }
-+  public boolean add( final int k ) { synchronized( sync ) { return collection.add( k ); } }
-+  public boolean rem( final int k ) { synchronized( sync ) { return collection.rem( k ); } }
-+  public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
-+  public boolean addAll( final Collection<? extends Integer> c ) { synchronized( sync ) { return collection.addAll( c ); } }
-+  public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
-+  public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
-+  public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
-+  public void clear() { synchronized( sync ) { collection.clear(); } }
-+  public String toString() { synchronized( sync ) { return collection.toString(); } }
-+ }
-+ /** Returns a synchronized collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static IntCollection synchronize( final IntCollection c ) { return new SynchronizedCollection ( c ); }
-+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @param sync an object that will be used to synchronize the list access.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static IntCollection synchronize( final IntCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
-+ /** An unmodifiable wrapper class for collections. */
-+ public static class UnmodifiableCollection implements IntCollection , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntCollection collection;
-+  protected UnmodifiableCollection( final IntCollection c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+  }
-+  public int size() { return collection.size(); }
-+  public boolean isEmpty() { return collection.isEmpty(); }
-+  public boolean contains( final int o ) { return collection.contains( o ); }
-+  public IntIterator iterator() { return IntIterators.unmodifiable( collection.iterator() ); }
-+  @Deprecated
-+  public IntIterator intIterator() { return iterator(); }
-+  public boolean add( final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return collection.toString(); }
-+  public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
-+  public Object[] toArray() { return collection.toArray(); }
-+  public int[] toIntArray() { return collection.toIntArray(); }
-+  public int[] toIntArray( final int[] a ) { return collection.toIntArray( a ); }
-+  public int[] toArray( final int[] a ) { return collection.toArray( a ); }
-+  public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( final IntCollection c ) { return collection.containsAll( c ); }
-+  public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final Object k ) { return collection.contains( k ); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable view of the specified collection.
-+	 * @see java.util.Collections#unmodifiableCollection(Collection)
-+	 */
-+ public static IntCollection unmodifiable( final IntCollection c ) { return new UnmodifiableCollection ( c ); }
-+ /** A collection wrapper class for iterables. */
-+ public static class IterableCollection extends AbstractIntCollection implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntIterable iterable;
-+  protected IterableCollection( final IntIterable iterable ) {
-+   if ( iterable == null ) throw new NullPointerException();
-+   this.iterable = iterable;
-+  }
-+  public int size() {
-+   int c = 0;
-+   final IntIterator iterator = iterator();
-+   while( iterator.hasNext() ) {
-+    iterator.next();
-+    c++;
-+   }
-+   return c;
-+  }
-+  public boolean isEmpty() { return iterable.iterator().hasNext(); }
-+  public IntIterator iterator() { return iterable.iterator(); }
-+  @Deprecated
-+  public IntIterator intIterator() { return iterator(); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified iterable.
-+	 *
-+	 * @param iterable the iterable object to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable collection view of the specified iterable.
-+	 */
-+ public static IntCollection asCollection( final IntIterable iterable ) {
-+  if ( iterable instanceof IntCollection ) return (IntCollection )iterable;
-+  return new IterableCollection ( iterable );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Comparator;
-+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
-+ * and as primitive types. 
-+ *
-+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
-+ * can be used to implement this interface just by specifying the type-specific
-+ * comparator.
-+ *
-+ * @see Comparator
-+ */
-+public interface IntComparator extends Comparator<Integer> {
-+ /** Compares the given primitive types.
-+	 *
-+	 * @see java.util.Comparator
-+	 * @return A positive integer, zero, or a negative integer if the first
-+	 * argument is greater than, equal to, or smaller than, respectively, the
-+	 * second one.
-+	 */
-+ public int compare( int k1, int k2 );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** A class providing static methods and objects that do useful things with comparators.
-+ */
-+public class IntComparators {
-+ private IntComparators() {}
-+ /** A type-specific comparator mimicking the natural order. */
-+ protected static class NaturalImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  public final int compare( final int a, final int b ) {
-+   return ( Integer.compare((a),(b)) );
-+  }
-+        private Object readResolve() { return NATURAL_COMPARATOR; }
-+ };
-+
-+ public static final IntComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
-+ /** A type-specific comparator mimicking the opposite of the natural order. */
-+ protected static class OppositeImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  public final int compare( final int a, final int b ) {
-+   return - ( Integer.compare((a),(b)) );
-+  }
-+        private Object readResolve() { return OPPOSITE_COMPARATOR; }
-+ };
-+
-+ public static final IntComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
-+ protected static class OppositeComparator extends AbstractIntComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  private final IntComparator comparator;
-+  protected OppositeComparator( final IntComparator c ) {
-+   comparator = c;
-+  }
-+  public final int compare( final int a, final int b ) {
-+   return comparator.compare( b, a );
-+  }
-+ };
-+ /** Returns a comparator representing the opposite order of the given comparator. 
-+	 *
-+	 * @param c a comparator.
-+	 * @return a comparator representing the opposite order of <code>c</code>.
-+	 */
-+ public static IntComparator oppositeComparator( final IntComparator c ) {
-+  return new OppositeComparator ( c );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+/** A type-specific {@link Hash} interface.
-+ *
-+ * @see Hash
-+ */
-+public interface IntHash {
-+ /** A type-specific hash strategy.
-+	 *
-+	 * @see it.unimi.dsi.fastutil.Hash.Strategy
-+	 */
-+ public interface Strategy {
-+  /** Returns the hash code of the specified element with respect to this hash strategy.
-+		 *
-+		 * @param e an element.
-+		 * @return the hash code of the given element with respect to this hash strategy.
-+		 */
-+  public int hashCode( int e );
-+  /** Returns true if the given elements are equal with respect to this hash strategy.
-+		 *
-+		 * @param a an element.
-+		 * @param b another element.
-+		 * @return true if the two specified elements are equal with respect to this hash strategy.
-+		 */
-+  public boolean equals( int a, int b );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+/** A type-specific heap-based indirect priority queue. 
-+ *
-+ * <P>Instances of this class use an additional <em>inversion array</em>, of the same length of the reference array,
-+ * to keep track of the heap position containing a given element of the reference array. The priority queue is
-+ * represented using a heap. The heap is enlarged as needed, but it is never
-+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
-+ *
-+ * <P>This implementation does <em>not</em> allow one to enqueue several times the same index.
-+ */
-+public class IntHeapIndirectPriorityQueue extends IntHeapSemiIndirectPriorityQueue {
-+ /** The inversion array. */
-+ protected final int inv[];
-+ /** Creates a new empty queue with a given capacity and comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
-+  super( refArray, capacity, c );
-+  if ( capacity > 0 ) this.heap = new int[ capacity ];
-+  this.c = c;
-+  this.inv = new int[ refArray.length ];
-+  Arrays.fill( inv, -1 );
-+ }
-+ /** Creates a new empty queue with a given capacity and using the natural order.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity ) {
-+  this( refArray, capacity, null );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapIndirectPriorityQueue( int[] refArray, IntComparator c ) {
-+  this( refArray, refArray.length, c );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order. 
-+	 * @param refArray the reference array.
-+	 */
-+ public IntHeapIndirectPriorityQueue( int[] refArray ) {
-+  this( refArray, refArray.length, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final int size, final IntComparator c ) {
-+  this( refArray, 0, c );
-+  this.heap = a;
-+  this.size = size;
-+  int i = size;
-+  while( i-- != 0 ) {
-+   if ( inv[ a[ i ] ] != -1 ) throw new IllegalArgumentException( "Index " + a[ i ] + " appears twice in the heap" );
-+   inv[ a[ i ] ] = i;
-+  }
-+  IntIndirectHeaps.makeHeap( refArray, a, inv, size, c );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
-+  this( refArray, a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
-+  this( refArray, a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 */
-+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a ) {
-+  this( refArray, a, a.length );
-+ }
-+ public void enqueue( final int x ) {
-+  if ( inv[ x ] >= 0 ) throw new IllegalArgumentException( "Index " + x + " belongs to the queue" );
-+  if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
-+  inv[ heap[ size ] = x ] = size++;
-+  IntIndirectHeaps.upHeap( refArray, heap, inv, size, size - 1, c );
-+ }
-+ public boolean contains( final int index ) {
-+  return inv[ index ] >= 0;
-+ }
-+ public int dequeue() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int result = heap[ 0 ];
-+  if ( --size != 0 ) inv[ heap[ 0 ] = heap[ size ] ] = 0;
-+  inv[ result ] = -1;
-+  if ( size != 0 ) IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
-+  return result;
-+ }
-+ public void changed() {
-+  IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
-+ }
-+ public void changed( final int index ) {
-+  final int pos = inv[ index ];
-+  if ( pos < 0 ) throw new IllegalArgumentException( "Index " + index + " does not belong to the queue" );
-+  final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, pos, c );
-+  IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
-+ }
-+ /** Rebuilds this heap in a bottom-up fashion.
-+	 */
-+ public void allChanged() {
-+  IntIndirectHeaps.makeHeap( refArray, heap, inv, size, c );
-+ }
-+ public boolean remove( final int index ) {
-+  final int result = inv[ index ];
-+  if ( result < 0 ) return false;
-+  inv[ index ] = -1;
-+  if ( result < --size ) {
-+   inv[ heap[ result ] = heap[ size ] ] = result;
-+   final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, result, c );
-+   IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
-+  }
-+  return true;
-+ }
-+ public void clear() {
-+  size = 0;
-+  Arrays.fill( inv, -1 );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Iterator;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/** A type-specific heap-based priority queue.
-+ *
-+ * <P>Instances of this class represent a priority queue using a heap. The heap is enlarged as needed, but
-+ * it is never shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
-+ */
-+public class IntHeapPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
-+ private static final long serialVersionUID = 1L;
-+ /** The heap array. */
-+
-+ protected transient int[] heap = IntArrays.EMPTY_ARRAY;
-+ /** The number of elements in this queue. */
-+ protected int size;
-+ /** The type-specific comparator used in this queue. */
-+ protected IntComparator c;
-+ /** Creates a new empty queue with a given capacity and comparator.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+
-+ public IntHeapPriorityQueue( int capacity, IntComparator c ) {
-+  if ( capacity > 0 ) this.heap = new int[ capacity ];
-+  this.c = c;
-+ }
-+ /** Creates a new empty queue with a given capacity and using the natural order.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public IntHeapPriorityQueue( int capacity ) {
-+  this( capacity, null );
-+ }
-+ /** Creates a new empty queue with a given comparator.
-+	 *
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapPriorityQueue( IntComparator c ) {
-+  this( 0, c );
-+ }
-+ /** Creates a new empty queue using the natural order. 
-+	 */
-+ public IntHeapPriorityQueue() {
-+  this( 0, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapPriorityQueue( final int[] a, int size, final IntComparator c ) {
-+  this( c );
-+  this.heap = a;
-+  this.size = size;
-+  IntHeaps.makeHeap( a, size, c );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param a an array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapPriorityQueue( final int[] a, final IntComparator c ) {
-+  this( a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public IntHeapPriorityQueue( final int[] a, int size ) {
-+  this( a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param a an array.
-+	 */
-+ public IntHeapPriorityQueue( final int[] a ) {
-+  this( a, a.length );
-+ }
-+ /** Creates a queue using the elements in a type-specific collection using a given comparator.
-+	 *
-+	 * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
-+	 *
-+	 * @param collection a collection; its elements will be used to initialize the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapPriorityQueue( final IntCollection collection, final IntComparator c ) {
-+  this( collection.toIntArray(), c );
-+ }
-+ /** Creates a queue using the elements in a type-specific collection using the natural order.
-+	 *
-+	 * <P>This constructor is
-+	 * more efficient than enqueing the elements of <code>collection</code> one by one.
-+	 *
-+	 * @param collection a collection; its elements will be used to initialize the queue.
-+	 */
-+ public IntHeapPriorityQueue( final IntCollection collection ) {
-+  this( collection, null );
-+ }
-+ /** Creates a queue using the elements in a collection using a given comparator.
-+	 *
-+	 * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
-+	 *
-+	 * @param collection a collection; its elements will be used to initialize the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection, final IntComparator c ) {
-+  this( collection.size(), c );
-+  final Iterator<? extends Integer> iterator = collection.iterator();
-+  final int size = collection.size();
-+  for( int i = 0 ; i < size; i++ ) heap[ i ] = ((((Integer)(iterator.next())).intValue()));
-+ }
-+ /** Creates a queue using the elements in a collection using the natural order.
-+	 *
-+	 * <P>This constructor is
-+	 * more efficient than enqueing the elements of <code>collection</code> one by one.
-+	 *
-+	 * @param collection a collection; its elements will be used to initialize the queue.
-+	 */
-+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection ) {
-+  this( collection, null );
-+ }
-+ public void enqueue( int x ) {
-+  if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
-+  heap[ size++ ] = x;
-+  IntHeaps.upHeap( heap, size, size - 1, c );
-+ }
-+ public int dequeueInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int result = heap[ 0 ];
-+  heap[ 0 ] = heap[ --size ];
-+  if ( size != 0 ) IntHeaps.downHeap( heap, size, 0, c );
-+  return result;
-+ }
-+ public int firstInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return heap[ 0 ];
-+ }
-+ public void changed() {
-+  IntHeaps.downHeap( heap, size, 0, c );
-+ }
-+ public int size() { return size; }
-+ public void clear() {
-+  size = 0;
-+ }
-+ /** Trims the underlying heap array so that it has exactly {@link #size()} elements.
-+	 */
-+ public void trim() {
-+  heap = IntArrays.trim( heap, size );
-+ }
-+ public IntComparator comparator() { return c; }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  s.writeInt( heap.length );
-+  for( int i = 0; i < size; i++ ) s.writeInt( heap[ i ] );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  heap = new int[ s.readInt() ];
-+  for( int i = 0; i < size; i++ ) heap[ i ] = s.readInt();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
-+/** A type-specific heap-based semi-indirect priority queue. 
-+ *
-+ * <P>Instances of this class use as reference list a <em>reference array</em>,
-+ * which must be provided to each constructor. The priority queue is
-+ * represented using a heap. The heap is enlarged as needed, but it is never
-+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
-+ *
-+ * <P>This implementation allows one to enqueue several time the same index, but
-+ * you must be careful when calling {@link #changed()}.
-+ */
-+public class IntHeapSemiIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
-+ /** The reference array. */
-+ protected final int refArray[];
-+ /** The semi-indirect heap. */
-+ protected int heap[] = IntArrays.EMPTY_ARRAY;
-+ /** The number of elements in this queue. */
-+ protected int size;
-+ /** The type-specific comparator used in this queue. */
-+ protected IntComparator c;
-+ /** Creates a new empty queue without elements with a given capacity and comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
-+  if ( capacity > 0 ) this.heap = new int[ capacity ];
-+  this.refArray = refArray;
-+  this.c = c;
-+ }
-+ /** Creates a new empty queue with given capacity and using the natural order.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity ) {
-+  this( refArray, capacity, null );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, IntComparator c ) {
-+  this( refArray, refArray.length, c );
-+ }
-+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order. 
-+	 * @param refArray the reference array.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray ) {
-+  this( refArray, refArray.length, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
-+  this( refArray, 0, c );
-+  this.heap = a;
-+  this.size = size;
-+  IntSemiIndirectHeaps.makeHeap( refArray, a, size, c );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
-+  this( refArray, a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
-+  this( refArray, a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 * The elements of the array will be rearranged so to form a heap (this is
-+	 * more efficient than enqueing the elements of <code>a</code> one by one).
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param a an array of indices into <code>refArray</code>.
-+	 */
-+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a ) {
-+  this( refArray, a, a.length );
-+ }
-+ /** Ensures that the given index is a valid reference.
-+	 *
-+	 * @param index an index in the reference array.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
-+	 */
-+ protected void ensureElement( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
-+ }
-+ public void enqueue( int x ) {
-+  ensureElement( x );
-+  if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
-+  heap[ size++ ] = x;
-+  IntSemiIndirectHeaps.upHeap( refArray, heap, size, size - 1, c );
-+ }
-+ public int dequeue() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int result = heap[ 0 ];
-+  heap[ 0 ] = heap[ --size ];
-+  if ( size != 0 ) IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
-+  return result;
-+ }
-+ public int first() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return heap[ 0 ];
-+ }
-+ /** {@inheritDoc}
-+	 *
-+	 * <P>The caller <strong>must</strong> guarantee that when this method is called the
-+	 * index of the first element appears just once in the queue. Failure to do so
-+	 * will bring the queue in an inconsistent state, and will cause
-+	 * unpredictable behaviour.
-+	 */
-+ public void changed() {
-+  IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
-+ }
-+ /** Rebuilds this heap in a bottom-up fashion.
-+	 */
-+ public void allChanged() {
-+  IntSemiIndirectHeaps.makeHeap( refArray, heap, size, c );
-+ }
-+ public int size() { return size; }
-+ public void clear() { size = 0; }
-+ /** Trims the backing array so that it has exactly {@link #size()} elements.
-+	 */
-+ public void trim() {
-+  heap = IntArrays.trim( heap, size );
-+ }
-+ public IntComparator comparator() { return c; }
-+ public int front( final int[] a ) {
-+  return c == null ? IntSemiIndirectHeaps.front( refArray, heap, size, a ) : IntSemiIndirectHeaps.front( refArray, heap, size, a, c );
-+ }
-+ public String toString() {
-+  StringBuffer s = new StringBuffer();
-+  s.append( "[" );
-+  for ( int i = 0; i < size; i++ ) {
-+   if ( i != 0 ) s.append( ", " );
-+   s.append( refArray[ heap [ i ] ] );
-+  }
-+  s.append( "]" );
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** A class providing static methods and objects that do useful things with heaps.
-+ *
-+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
-+ * are used in the implementation of heap-based queues, but they may be also used
-+ * directly.
-+ *
-+ */
-+public class IntHeaps {
-+ private IntHeaps() {}
-+ /** Moves the given element down into the heap until it reaches the lowest possible position.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index of the element that must be moved down.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position of the element of index <code>i</code>.
-+	 */
-+
-+ public static int downHeap( final int[] heap, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  int child;
-+  if ( c == null )
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
-+    if ( ( (e) <= (t) ) ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  else
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
-+    if ( c.compare( e, t ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Moves the given element up in the heap until it reaches the highest possible position.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index of the element that must be moved up.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position of the element of index <code>i</code>.
-+	 */
-+
-+ public static int upHeap( final int[] heap, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  if ( c == null )
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( ( (t) <= (e) ) ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  else
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( c.compare( t, e ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Makes an array into a heap.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final int[] heap, final int size, final IntComparator c ) {
-+  int i = size >>> 1;
-+  while( i-- != 0 ) downHeap( heap, size, i, c );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Arrays;
-+/** A class providing static methods and objects that do useful things with indirect heaps.
-+ *
-+ * <P>An indirect heap is an extension of a semi-indirect heap using also an
-+ * <em>inversion array</em> of the same length as the reference array,
-+ * satisfying the relation <code>heap[inv[i]]==i</code> when
-+ * <code>inv[i]&gt;=0</code>, and <code>inv[heap[i]]==i</code> for all elements in the heap.
-+ */
-+public class IntIndirectHeaps {
-+ private IntIndirectHeaps() {}
-+ /** Moves the given element down into the indirect heap until it reaches the lowest possible position.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param heap the indirect heap (starting at 0).
-+	 * @param inv the inversion array.
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index in the heap of the element to be moved down.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position in the heap of the element of heap index <code>i</code>.
-+	 */
-+
-+ public static int downHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  final int E = refArray[ e ];
-+  int child;
-+  if ( c == null )
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
-+    if ( ( (E) <= (refArray[ t ]) ) ) break;
-+    heap[ i ] = t;
-+    inv[ heap[ i ] ] = i;
-+    i = child;
-+   }
-+  else
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
-+    if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
-+    heap[ i ] = t;
-+    inv[ heap[ i ] ] = i;
-+    i = child;
-+   }
-+  heap[ i ] = e;
-+  inv[ e ] = i;
-+  return i;
-+ }
-+ /** Moves the given element up in the indirect heap until it reaches the highest possible position.
-+	 *
-+	 * Note that in principle after this call the heap property may be violated.
-+	 * 
-+	 * @param refArray the reference array.
-+	 * @param heap the indirect heap (starting at 0).
-+	 * @param inv the inversion array.
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index in the heap of the element to be moved up.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position in the heap of the element of heap index <code>i</code>.
-+	 */
-+
-+ public static int upHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  final int E = refArray[ e ];
-+  if ( c == null )
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( ( (refArray[ t ]) <= (E) ) ) break;
-+    heap[ i ] = t;
-+    inv[ heap[ i ] ] = i;
-+    i = parent;
-+   }
-+  else
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( c.compare( refArray[ t ], E ) <= 0 ) break;
-+    heap[ i ] = t;
-+    inv[ heap[ i ] ] = i;
-+    i = parent;
-+   }
-+  heap[ i ] = e;
-+  inv[ e ] = i;
-+  return i;
-+ }
-+ /** Creates an indirect heap in the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param offset the first element of the reference array to be put in the heap.
-+	 * @param length the number of elements to be put in the heap.
-+	 * @param heap the array where the heap is to be created.
-+	 * @param inv the inversion array.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final int[] inv, final IntComparator c ) {
-+  IntArrays.ensureOffsetLength( refArray, offset, length );
-+  if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
-+  if ( inv.length < refArray.length ) throw new IllegalArgumentException( "The inversion array length (" + heap.length + ") is smaller than the length of the reference array (" + refArray.length + ")" );
-+  Arrays.fill( inv, 0, refArray.length, -1 );
-+  int i = length;
-+  while( i-- != 0 ) inv[ heap[ i ] = offset + i ] = i;
-+  i = length >>> 1;
-+  while( i-- != 0 ) downHeap( refArray, heap, inv, length, i, c );
-+ }
-+ /** Creates an indirect heap from a given index array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param heap an array containing indices into <code>refArray</code>.
-+	 * @param inv the inversion array.
-+	 * @param size the number of elements in the heap.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, final IntComparator c ) {
-+  int i = size >>> 1;
-+  while( i-- != 0 ) downHeap( refArray, heap, inv, size, i, c );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.IndirectPriorityQueue;
-+/** A type-specific {@link IndirectPriorityQueue}. 
-+ *
-+ * <P>Additionally, this interface strengthens {@link #comparator()}.
-+ */
-+public interface IntIndirectPriorityQueue extends IndirectPriorityQueue<Integer> {
-+    /** Returns the comparator associated with this queue.
-+	 *
-+	 * Note that this specification strengthens the one given in {@link IndirectPriorityQueue}.
-+	 *
-+	 * @return the comparator associated with this queue.
-+	 * @see IndirectPriorityQueue#comparator()
-+	 */
-+ IntComparator comparator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.lang.Iterable;
-+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
-+ *
-+ * <p><strong>Warning</strong>: Java will let you write &ldquo;colon&rdquo; <code>for</code> statements with primitive-type
-+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
-+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
-+ *
-+ * @see Iterable
-+ */
-+public interface IntIterable extends Iterable<Integer> {
-+ /** Returns a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
-+	 *
-+	 * @return a type-specific iterator.
-+	 */
-+ IntIterator iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Iterator;
-+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
-+ * the possibility to skip elements.
-+ *
-+ * @see Iterator
-+ */
-+public interface IntIterator extends Iterator<Integer> {
-+ /**
-+	 * Returns the next element as a primitive type.
-+	 *
-+	 * @return the next element in the iteration.
-+	 * @see Iterator#next()
-+	 */
-+ int nextInt();
-+ /** Skips the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #next()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasNext()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip.
-+	 * @return the number of elements actually skipped.
-+	 * @see Iterator#next()
-+	 */
-+ int skip( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific iterators.
-+ *
-+ * @see Iterator
-+ */
-+public class IntIterators {
-+ private IntIterators() {}
-+ /** A class returning no elements and a type-specific iterator interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific iterator.
-+	 */
-+ public static class EmptyIterator extends AbstractIntListIterator implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyIterator() {}
-+  public boolean hasNext() { return false; }
-+  public boolean hasPrevious() { return false; }
-+  public int nextInt() { throw new NoSuchElementException(); }
-+  public int previousInt() { throw new NoSuchElementException(); }
-+  public int nextIndex() { return 0; }
-+  public int previousIndex() { return -1; }
-+  public int skip( int n ) { return 0; };
-+  public int back( int n ) { return 0; };
-+  public Object clone() { return EMPTY_ITERATOR; }
-+        private Object readResolve() { return EMPTY_ITERATOR; }
-+ }
-+ /** An empty iterator (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>The class of this objects represent an abstract empty iterator
-+	 * that can iterate as a type-specific (list) iterator.
-+	 */
-+
-+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
-+ /** An iterator returning a single element. */
-+ private static class SingletonIterator extends AbstractIntListIterator {
-+  private final int element;
-+  private int curr;
-+  public SingletonIterator( final int element ) {
-+   this.element = element;
-+  }
-+  public boolean hasNext() { return curr == 0; }
-+  public boolean hasPrevious() { return curr == 1; }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = 1;
-+   return element;
-+  }
-+  public int previousInt() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = 0;
-+   return element;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Returns an iterator that iterates just over the given element.
-+	 *
-+	 * @param element the only element to be returned by a type-specific list iterator.
-+	 * @return  an iterator that iterates just over <code>element</code>.
-+	 */
-+ public static IntListIterator singleton( final int element ) {
-+  return new SingletonIterator ( element );
-+ }
-+ /** A class to wrap arrays in iterators. */
-+ private static class ArrayIterator extends AbstractIntListIterator {
-+  private final int[] array;
-+  private final int offset, length;
-+  private int curr;
-+  public ArrayIterator( final int[] array, final int offset, final int length ) {
-+   this.array = array;
-+   this.offset = offset;
-+   this.length = length;
-+  }
-+  public boolean hasNext() { return curr < length; }
-+  public boolean hasPrevious() { return curr > 0; }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   return array[ offset + curr++ ];
-+  }
-+  public int previousInt() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   return array[ offset + --curr ];
-+  }
-+  public int skip( int n ) {
-+   if ( n <= length - curr ) {
-+    curr += n;
-+    return n;
-+   }
-+   n = length - curr;
-+   curr = length;
-+   return n;
-+  }
-+  public int back( int n ) {
-+   if ( n <= curr ) {
-+    curr -= n;
-+    return n;
-+   }
-+   n = curr;
-+   curr = 0;
-+   return n;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Wraps the given part of an array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will iterate
-+	 * <code>length</code> times, returning consecutive elements of the given
-+	 * array starting from the one with index <code>offset</code>.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param length the number of elements to return.
-+	 * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
-+	 */
-+ public static IntListIterator wrap( final int[] array, final int offset, final int length ) {
-+  IntArrays.ensureOffsetLength( array, offset, length );
-+  return new ArrayIterator ( array, offset, length );
-+ }
-+ /** Wraps the given array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will return
-+	 * all elements of the given array.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @return an iterator that will the elements of <code>array</code>.
-+	 */
-+ public static IntListIterator wrap( final int[] array ) {
-+  return new ArrayIterator ( array, 0, array.length );
-+ }
-+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static int unwrap( final IntIterator i, final int array[], int offset, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextInt();
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given array. The iteration will stop when the
-+	 * iterator has no more elements or when the end of the array has been reached.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static int unwrap( final IntIterator i, final int array[] ) {
-+  return unwrap( i, array, 0, array.length );
-+ }
-+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator. At most <code>max</code> elements
-+	 * will be returned.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be unwrapped.
-+	 * @return an array containing the elements returned by the iterator (at most <code>max</code>).
-+	 */
-+
-+ public static int[] unwrap( final IntIterator i, int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int array[] = new int[ 16 ];
-+  int j = 0;
-+  while( max-- != 0 && i.hasNext() ) {
-+   if ( j == array.length ) array = IntArrays.grow( array, j + 1 );
-+   array[ j++ ] = i.nextInt();
-+  }
-+  return IntArrays.trim( array, j );
-+ }
-+ /** Unwraps an iterator, returning an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return an array containing the elements returned by the iterator.
-+	 */
-+ public static int[] unwrap( final IntIterator i ) {
-+  return unwrap( i, Integer.MAX_VALUE );
-+ }
-+ /** Unwraps an iterator into a type-specific collection,  with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection array to contain the output of the iterator.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int unwrap( final IntIterator i, final IntCollection c, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) c.add( i.nextInt() );
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given type-specific collection. The returned count on the number
-+	 * unwrapped elements is a long, so that it will work also with very large collections.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection to contain the output of the iterator.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static long unwrap( final IntIterator i, final IntCollection c ) {
-+  long n = 0;
-+  while( i.hasNext() ) {
-+   c.add( i.nextInt() );
-+   n++;
-+  }
-+  return n;
-+ }
-+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection (up to <code>max</code>).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int pour( final IntIterator i, final IntCollection s, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) s.add( i.nextInt() );
-+  return max - j - 1;
-+ }
-+ /** Pours an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int pour( final IntIterator i, final IntCollection s ) {
-+  return pour( i, s, Integer.MAX_VALUE );
-+ }
-+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return a type-specific list containing the returned elements, up to <code>max</code>.
-+	 */
-+ public static IntList pour( final IntIterator i, int max ) {
-+  final IntArrayList l = new IntArrayList ();
-+  pour( i, l, max );
-+  l.trim();
-+  return l;
-+ }
-+ /** Pours an iterator, returning a type-specific list.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a list containing the returned elements. Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return a type-specific list containing the returned elements.
-+	 */
-+ public static IntList pour( final IntIterator i ) {
-+  return pour( i, Integer.MAX_VALUE );
-+ }
-+ private static class IteratorWrapper extends AbstractIntIterator {
-+  final Iterator<Integer> i;
-+  public IteratorWrapper( final Iterator<Integer> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public void remove() { i.remove(); }
-+  public int nextInt() { return ((i.next()).intValue()); }
-+ }
-+ /** Wraps a standard iterator into a type-specific iterator.
-+	 *
-+	 * <P>This method wraps a standard iterator into a type-specific one which will handle the
-+	 * type conversions for you. Of course, any attempt to wrap an iterator returning the
-+	 * instances of the wrong class will generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i an iterator.
-+	 * @return a type-specific iterator  backed by <code>i</code>.
-+	 */
-+ @SuppressWarnings({"unchecked","rawtypes"})
-+  public static IntIterator asIntIterator( final Iterator i ) {
-+  if ( i instanceof IntIterator ) return (IntIterator )i;
-+  return new IteratorWrapper ( i );
-+ }
-+ private static class ListIteratorWrapper extends AbstractIntListIterator {
-+  final ListIterator<Integer> i;
-+  public ListIteratorWrapper( final ListIterator<Integer> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+  public void set( int k ) { i.set( (Integer.valueOf(k)) ); }
-+  public void add( int k ) { i.add( (Integer.valueOf(k)) ); }
-+  public void remove() { i.remove(); }
-+  public int nextInt() { return ((i.next()).intValue()); }
-+  public int previousInt() { return ((i.previous()).intValue()); }
-+ }
-+ /** Wraps a standard list iterator into a type-specific list iterator.
-+	 *
-+	 * <P>This method wraps a standard list iterator into a type-specific one
-+	 * which will handle the type conversions for you. Of course, any attempt
-+	 * to wrap an iterator returning the instances of the wrong class will
-+	 * generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i a list iterator.
-+	 * @return a type-specific list iterator backed by <code>i</code>.
-+	 */
-+ @SuppressWarnings({"unchecked","rawtypes"})
-+  public static IntListIterator asIntIterator( final ListIterator i ) {
-+  if ( i instanceof IntListIterator ) return (IntListIterator )i;
-+  return new ListIteratorWrapper ( i );
-+ }
-+ private static class IntervalIterator extends AbstractIntListIterator {
-+  private final int from, to;
-+  int curr;
-+  public IntervalIterator( final int from, final int to ) {
-+   this.from = this.curr = from;
-+   this.to = to;
-+  }
-+  public boolean hasNext() { return curr < to; }
-+  public boolean hasPrevious() { return curr > from; }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   return curr++;
-+  }
-+  public int previousInt() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   return --curr;
-+  }
-+  public int nextIndex() { return curr - from; }
-+  public int previousIndex() { return curr - from - 1; }
-+  public int skip( int n ) {
-+   if ( curr + n <= to ) {
-+    curr += n;
-+    return n;
-+   }
-+   n = to - curr;
-+   curr = to;
-+   return n;
-+  }
-+  public int back( int n ) {
-+   if ( curr - n >= from ) {
-+    curr -= n;
-+    return n;
-+   }
-+   n = curr - from ;
-+   curr = from;
-+   return n;
-+  }
-+ }
-+ /** Creates a type-specific list iterator over an interval.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will return the
-+	 * elements <code>from</code>, <code>from+1</code>,&hellip;, <code>to-1</code>.
-+	 *
-+	 * @param from the starting element (inclusive).
-+	 * @param to the ending element (exclusive).
-+	 * @return a type-specific list iterator enumerating the elements from <code>from</code> to <code>to</code>.
-+	 */
-+ public static IntListIterator fromTo( final int from, final int to ) {
-+  return new IntervalIterator( from, to );
-+ }
-+ private static class IteratorConcatenator extends AbstractIntIterator {
-+  final IntIterator a[];
-+  int offset, length, lastOffset = -1;
-+  public IteratorConcatenator( final IntIterator a[], int offset, int length ) {
-+   this.a = a;
-+   this.offset = offset;
-+   this.length = length;
-+   advance();
-+  }
-+  private void advance() {
-+   while( length != 0 ) {
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return;
-+  }
-+  public boolean hasNext() {
-+   return length > 0;
-+  }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   int next = a[ lastOffset = offset ].nextInt();
-+   advance();
-+   return next;
-+  }
-+  public void remove() {
-+   if ( lastOffset == -1 ) throw new IllegalStateException();
-+   a[ lastOffset ].remove();
-+  }
-+  public int skip( int n ) {
-+   lastOffset = -1;
-+   int skipped = 0;
-+   while( skipped < n && length != 0 ) {
-+    skipped += a[ offset ].skip( n - skipped );
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return skipped;
-+  }
-+ }
-+ /** Concatenates all iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by all iterators contained in the given array.
-+	 *
-+	 * @param a an array of iterators.
-+	 * @return an iterator obtained by concatenation.
-+	 */
-+ public static IntIterator concat( final IntIterator a[] ) {
-+  return concat( a, 0, a.length );
-+ }
-+ /** Concatenates a sequence of iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by <code>a[ offset ]</code>, then those returned 
-+	 * by <code>a[ offset + 1 ]</code>, and so on up to 
-+	 * <code>a[ offset + length - 1 ]</code>. 
-+	 *
-+	 * @param a an array of iterators.
-+	 * @param offset the index of the first iterator to concatenate.
-+	 * @param length the number of iterators to concatenate.
-+	 * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
-+	 */
-+ public static IntIterator concat( final IntIterator a[], final int offset, final int length ) {
-+  return new IteratorConcatenator ( a, offset, length );
-+ }
-+   /** An unmodifiable wrapper class for iterators. */
-+ public static class UnmodifiableIterator extends AbstractIntIterator {
-+  final protected IntIterator i;
-+  public UnmodifiableIterator( final IntIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public int nextInt() { return i.nextInt(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer next() { return i.next(); }
-+ }
-+ /** Returns an unmodifiable iterator backed by the specified iterator.
-+	 *
-+	 * @param i the iterator to be wrapped in an unmodifiable iterator.
-+	 * @return an unmodifiable view of the specified iterator.
-+	 */
-+ public static IntIterator unmodifiable( final IntIterator i ) { return new UnmodifiableIterator ( i ); }
-+   /** An unmodifiable wrapper class for bidirectional iterators. */
-+ public static class UnmodifiableBidirectionalIterator extends AbstractIntBidirectionalIterator {
-+  final protected IntBidirectionalIterator i;
-+  public UnmodifiableBidirectionalIterator( final IntBidirectionalIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public int nextInt() { return i.nextInt(); }
-+  public int previousInt() { return i.previousInt(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer next() { return i.next(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer previous() { return i.previous(); }
-+ }
-+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
-+	 *
-+	 * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
-+	 * @return an unmodifiable view of the specified bidirectional iterator.
-+	 */
-+ public static IntBidirectionalIterator unmodifiable( final IntBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
-+   /** An unmodifiable wrapper class for list iterators. */
-+ public static class UnmodifiableListIterator extends AbstractIntListIterator {
-+  final protected IntListIterator i;
-+  public UnmodifiableListIterator( final IntListIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public int nextInt() { return i.nextInt(); }
-+  public int previousInt() { return i.previousInt(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer next() { return i.next(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Integer previous() { return i.previous(); }
-+ }
-+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
-+	 *
-+	 * @param i the list iterator to be wrapped in an unmodifiable list iterator.
-+	 * @return an unmodifiable view of the specified list iterator.
-+	 */
-+ public static IntListIterator unmodifiable( final IntListIterator i ) { return new UnmodifiableListIterator ( i ); }
-+ 
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.NoSuchElementException;
-+/**  A type-specific linked hash set with with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a set. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
-+ * have been added to the set (addition of elements already present 
-+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
-+ * order of the keys. The order is kept by means of a doubly linked list, represented
-+ * <i>via</i> an array of longs parallel to the table.
-+ *
-+ * <P>This class implements the interface of a sorted set, so to allow easy
-+ * access of the iteration order: for instance, you can get the first element
-+ * in iteration order with {@code first()} without having to create an
-+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
-+ * contract because all subset methods throw an exception and {@link
-+ * #comparator()} returns always <code>null</code>.
-+ *
-+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
-+ * to use instances of this class as a cache (e.g., with LRU policy).
-+ *
-+ * <P>The iterators provided by this class are type-specific {@linkplain
-+ * java.util.ListIterator list iterators}, and can be started at any
-+ * element <em>which is in the set</em> (if the provided element 
-+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
-+ * If, however, the provided element is not the first or last element in the
-+ * set, the first access to the list index will require linear time, as in the worst case
-+ * the entire set must be scanned in iteration order to retrieve the positional
-+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
-+ * however, all operations will be performed in constant time.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class IntLinkedOpenCustomHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient int[] key;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the null key. */
-+ protected transient boolean containsNull;
-+ /** The hash strategy of this custom set. */
-+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
-+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int first = -1;
-+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int last = -1;
-+ /** For each entry, the next and the previous entry in iteration order,
-+     * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
-+     * The first entry contains predecessor -1, and the last entry 
-+     * contains successor -1. */
-+ protected transient long[] link;
-+ /** The current table size. Note that an additional element is allocated for storing the null key. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the null key, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Creates a new hash set.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+
-+ public IntLinkedOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this.strategy = strategy;
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new int[ n + 1 ];
-+  link = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( expected, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+ this( c.size(), f, strategy );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( c, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final IntCollection c, final float f, it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+ this( c.size(), f, strategy );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final IntCollection c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( c, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final IntIterator i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( DEFAULT_INITIAL_SIZE, f, strategy );
-+  while( i.hasNext() ) add( i.nextInt() );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final IntIterator i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( i, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( IntIterators.asIntIterator( i ), f, strategy );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( IntIterators.asIntIterator( i ), strategy );
-+ }
-+ /** Creates a new hash set and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+ this( length < 0 ? 0 : length, f, strategy );
-+  IntArrays.ensureOffsetLength( a, offset, length );
-+  for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final int[] a, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( a, 0, a.length, f, strategy );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public IntLinkedOpenCustomHashSet( final int[] a, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
-+  this( a, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Returns the hashing strategy.
-+	 *
-+	 * @return the hashing strategy of this custom hash set.
-+	 */
-+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
-+  return strategy;
-+ }
-+ private int realSize() {
-+  return containsNull ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( IntCollection c ) {
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( Collection<? extends Integer> c ) {
-+  // The resulting collection will be at least c.size() big
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ public boolean add( final int k ) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNull ) return false;
-+   pos = n;
-+   containsNull = true;
-+   key[ n ] = k;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( strategy.equals( (curr), (k) ) ) ) return false;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( strategy.equals( (curr), (k) ) ) ) return false;
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  int curr;
-+  final int[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   fixPointers( pos, last );
-+  }
-+ }
-+ private boolean removeEntry( final int pos ) {
-+  size--;
-+  fixPointers( pos );
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+ private boolean removeNullEntry() {
-+  containsNull = false;
-+  key[ n ] = (0);
-+  size--;
-+  fixPointers( n );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+
-+ public boolean remove( final int k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) {
-+   if ( containsNull ) return removeNullEntry();
-+   return false;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  }
-+ }
-+
-+ public boolean contains( final int k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  }
-+ }
-+ /** Removes the first key in iteration order.
-+	 * @return the first key.
-+	 * @throws NoSuchElementException is this set is empty.
-+	 */
-+ public int removeFirstInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = first;
-+  // Abbreviated version of fixPointers(pos)
-+  first = (int) link[ pos ];
-+  if ( 0 <= first ) {
-+   // Special case of SET_PREV( link[ first ], -1 )
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  final int k = key[ pos ];
-+  size--;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   containsNull = false;
-+   key[ n ] = (0);
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return k;
-+ }
-+ /** Removes the the last key in iteration order.
-+	 * @return the last key.
-+	 * @throws NoSuchElementException is this set is empty.
-+	 */
-+ public int removeLastInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = last;
-+  // Abbreviated version of fixPointers(pos)
-+  last = (int) ( link[ pos ] >>> 32 );
-+  if ( 0 <= last ) {
-+   // Special case of SET_NEXT( link[ last ], -1 )
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  final int k = key[ pos ];
-+  size--;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   containsNull = false;
-+   key[ n ] = (0);
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return k;
-+ }
-+ private void moveIndexToFirst( final int i ) {
-+  if ( size == 1 || first == i ) return;
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   // Special case of SET_NEXT( link[ last ], -1 );
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+  first = i;
-+ }
-+ private void moveIndexToLast( final int i ) {
-+  if ( size == 1 || last == i ) return;
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   // Special case of SET_PREV( link[ first ], -1 );
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+  last = i;
-+ }
-+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return true if the key was not present.
-+	 */
-+ public boolean addAndMoveToFirst( final int k ) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNull ) {
-+    moveIndexToFirst( n );
-+    return false;
-+   }
-+   containsNull = true;
-+   pos = n;
-+  }
-+  else {
-+   // The starting point.
-+   final int key[] = this.key;
-+   pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+   // There's always an unused entry. TODO
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
-+     moveIndexToFirst( pos );
-+     return false;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+  }
-+  key[ pos ] = k;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+   first = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return true if the key was not present.
-+	 */
-+ public boolean addAndMoveToLast( final int k ) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNull ) {
-+    moveIndexToLast( n );
-+    return false;
-+   }
-+   containsNull = true;
-+   pos = n;
-+  }
-+  else {
-+   // The starting point.
-+   final int key[] = this.key;
-+   pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
-+     moveIndexToLast( pos );
-+     return false;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+  }
-+  key[ pos ] = k;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /* Removes all elements from this set.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNull = false;
-+  Arrays.fill( key, (0) );
-+  first = last = -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** Modifies the {@link #link} vector so that the given entry is removed.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param i the index of an entry. 
-+	 */
-+ protected void fixPointers( final int i ) {
-+  if ( size == 0 ) {
-+   first = last = -1;
-+   return;
-+  }
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   if (0 <= first) {
-+    // Special case of SET_PREV( link[ first ], -1 )
-+    link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+   }
-+   return;
-+  }
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   if (0 <= last) {
-+    // Special case of SET_NEXT( link[ last ], -1 )
-+    link[ last ] |= -1 & 0xFFFFFFFFL;
-+   }
-+   return;
-+  }
-+  final long linki = link[ i ];
-+  final int prev = (int) ( linki >>> 32 );
-+  final int next = (int) linki;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+ }
-+ /** Modifies the {@link #link} vector for a shift from s to d.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param s the source position.
-+	 * @param d the destination position.
-+	 */
-+ protected void fixPointers( int s, int d ) {
-+  if ( size == 1 ) {
-+   first = last = d;
-+   // Special case of SET(link[ d ], -1, -1)
-+   link[ d ] = -1L;
-+   return;
-+  }
-+  if ( first == s ) {
-+   first = d;
-+   link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  if ( last == s ) {
-+   last = d;
-+   link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  final long links = link[ s ];
-+  final int prev = (int) ( links >>> 32 );
-+  final int next = (int) links;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ d ] = links;
-+ }
-+ /** Returns the first element of this set in iteration order.
-+	 *
-+	 * @return the first element in iteration order.
-+	 */
-+ public int firstInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ first ];
-+ }
-+ /** Returns the last element of this set in iteration order.
-+	 *
-+	 * @return the last element in iteration order.
-+	 */
-+ public int lastInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ last ];
-+ }
-+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
-+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
-+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
-+ public IntComparator comparator() { return null; }
-+ /** A list iterator over a linked set.
-+	 *
-+	 * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time. 
-+	 */
-+ private class SetIterator extends AbstractIntListIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  int prev = -1;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  int next = -1;
-+  /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
-+  int curr = -1;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
-+  int index = -1;
-+  SetIterator() {
-+   next = first;
-+   index = 0;
-+  }
-+  SetIterator( int from ) {
-+   if ( ( strategy.equals( (from), (0) ) ) ) {
-+    if ( IntLinkedOpenCustomHashSet.this.containsNull ) {
-+     next = (int) link[ n ];
-+     prev = n;
-+     return;
-+    }
-+    else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
-+   }
-+   if ( ( strategy.equals( (key[ last ]), (from) ) ) ) {
-+    prev = last;
-+    index = size;
-+    return;
-+   }
-+   // The starting point.
-+   final int key[] = IntLinkedOpenCustomHashSet.this.key;
-+   int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(from) ) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( strategy.equals( (key[ pos ]), (from) ) ) ) {
-+     // Note: no valid index known.
-+     next = (int) link[ pos ];
-+     prev = pos;
-+     return;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
-+  }
-+  public boolean hasNext() { return next != -1; }
-+  public boolean hasPrevious() { return prev != -1; }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = next;
-+   next = (int) link[ curr ];
-+   prev = curr;
-+   if ( index >= 0 ) index++;
-+   if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
-+   return key[ curr ];
-+  }
-+  public int previousInt() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = prev;
-+   prev = (int) ( link[ curr ] >>> 32 );
-+   next = curr;
-+   if ( index >= 0 ) index--;
-+   return key[ curr ];
-+  }
-+  private final void ensureIndexKnown() {
-+   if ( index >= 0 ) return;
-+   if ( prev == -1 ) {
-+    index = 0;
-+    return;
-+   }
-+   if ( next == -1 ) {
-+    index = size;
-+    return;
-+   }
-+   int pos = first;
-+   index = 1;
-+   while( pos != prev ) {
-+    pos = (int) link[ pos ];
-+    index++;
-+   }
-+  }
-+  public int nextIndex() {
-+   ensureIndexKnown();
-+   return index;
-+  }
-+  public int previousIndex() {
-+   ensureIndexKnown();
-+   return index - 1;
-+  }
-+  public void remove() {
-+   ensureIndexKnown();
-+   if ( curr == -1 ) throw new IllegalStateException();
-+   if ( curr == prev ) {
-+    /* If the last operation was a next(), we are removing an entry that preceeds
-+				   the current index, and thus we must decrement it. */
-+    index--;
-+    prev = (int) ( link[ curr ] >>> 32 );
-+   }
-+   else
-+    next = (int) link[ curr ];
-+   size--;
-+   /* Now we manually fix the pointers. Because of our knowledge of next
-+			   and prev, this is going to be faster than calling fixPointers(). */
-+   if ( prev == -1 ) first = next;
-+   else
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   if ( next == -1 ) last = prev;
-+   else
-+    link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   int last, slot, pos = curr;
-+   curr = -1;
-+   if ( pos == n ) {
-+    IntLinkedOpenCustomHashSet.this.containsNull = false;
-+    IntLinkedOpenCustomHashSet.this.key[ n ] = (0);
-+   }
-+   else {
-+    int curr;
-+    final int[] key = IntLinkedOpenCustomHashSet.this.key;
-+    // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.			
-+    for(;;) {
-+     pos = ( ( last = pos ) + 1 ) & mask;
-+     for(;;) {
-+      if ( ( (curr = key[ pos ]) == (0) ) ) {
-+       key[ last ] = (0);
-+       return;
-+      }
-+      slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+      if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+      pos = ( pos + 1 ) & mask;
-+     }
-+     key[ last ] = curr;
-+     if ( next == pos ) next = last;
-+     if ( prev == pos ) prev = last;
-+     fixPointers( pos, last );
-+    }
-+   }
-+  }
-+ }
-+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
-+	 * Please see the class documentation for implementation details.
-+	 *
-+	 * @param from an element to start from.
-+	 * @return a type-specific list iterator starting at the given element.
-+	 * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
-+	 */
-+ public IntListIterator iterator( int from ) {
-+  return new SetIterator( from );
-+ }
-+ public IntListIterator iterator() {
-+  return new SetIterator();
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes this set, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing.
-+	 *
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this set if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this set in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing sets.  {@linkplain #clear() Clearing a
-+	 * set} leaves the table size untouched. If you are reusing a set
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient sets.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the set.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+
-+ protected void rehash( final int newN ) {
-+  final int key[] = this.key;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final int newKey[] = new int[ newN + 1 ];
-+  int i = first, prev = -1, newPrev = -1, t, pos;
-+  final long link[] = this.link;
-+  final long newLink[] = new long[ newN + 1 ];
-+  first = -1;
-+  for( int j = size; j-- != 0; ) {
-+   if ( ( strategy.equals( (key[ i ]), (0) ) ) ) pos = newN;
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask;
-+    while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   newKey[ pos ] = key[ i ];
-+   if ( prev != -1 ) {
-+    newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    newPrev = pos;
-+   }
-+   else {
-+    newPrev = first = pos;
-+    // Special case of SET(newLink[ pos ], -1, -1);
-+    newLink[ pos ] = -1L;
-+   }
-+   t = i;
-+   i = (int) link[ i ];
-+   prev = t;
-+  }
-+  this.link = newLink;
-+  this.last = newPrev;
-+  if ( newPrev != -1 )
-+   // Special case of SET_NEXT( newLink[ newPrev ], -1 );
-+   newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public IntLinkedOpenCustomHashSet clone() {
-+  IntLinkedOpenCustomHashSet c;
-+  try {
-+   c = (IntLinkedOpenCustomHashSet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.containsNull = containsNull;
-+  c.link = link.clone();
-+  c.strategy = strategy;
-+  return c;
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    h += ( strategy.hashCode(key[ i ]) );
-+   i++;
-+  }
-+  // Zero / null have hash zero.		
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final IntIterator i = iterator();
-+  s.defaultWriteObject();
-+  for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final int key[] = this.key = new int[ n + 1 ];
-+  final long link[] = this.link = new long[ n + 1 ];
-+  int prev = -1;
-+  first = last = -1;
-+  int k;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readInt();
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    pos = n;
-+    containsNull = true;
-+   }
-+   else {
-+    if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
-+     while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   }
-+   key[ pos ] = k;
-+   if ( first != -1 ) {
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    prev = pos;
-+   }
-+   else {
-+    prev = first = pos;
-+    // Special case of SET_PREV( newLink[ pos ], -1 );
-+    link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
-+   }
-+  }
-+  last = prev;
-+  if ( prev != -1 )
-+   // Special case of SET_NEXT( link[ prev ], -1 );
-+   link[ prev ] |= -1 & 0xFFFFFFFFL;
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.NoSuchElementException;
-+/**  A type-specific linked hash set with with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a set. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
-+ * have been added to the set (addition of elements already present 
-+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
-+ * order of the keys. The order is kept by means of a doubly linked list, represented
-+ * <i>via</i> an array of longs parallel to the table.
-+ *
-+ * <P>This class implements the interface of a sorted set, so to allow easy
-+ * access of the iteration order: for instance, you can get the first element
-+ * in iteration order with {@code first()} without having to create an
-+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
-+ * contract because all subset methods throw an exception and {@link
-+ * #comparator()} returns always <code>null</code>.
-+ *
-+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
-+ * to use instances of this class as a cache (e.g., with LRU policy).
-+ *
-+ * <P>The iterators provided by this class are type-specific {@linkplain
-+ * java.util.ListIterator list iterators}, and can be started at any
-+ * element <em>which is in the set</em> (if the provided element 
-+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
-+ * If, however, the provided element is not the first or last element in the
-+ * set, the first access to the list index will require linear time, as in the worst case
-+ * the entire set must be scanned in iteration order to retrieve the positional
-+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
-+ * however, all operations will be performed in constant time.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class IntLinkedOpenHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient int[] key;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the null key. */
-+ protected transient boolean containsNull;
-+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int first = -1;
-+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int last = -1;
-+ /** For each entry, the next and the previous entry in iteration order,
-+     * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
-+     * The first entry contains predecessor -1, and the last entry 
-+     * contains successor -1. */
-+ protected transient long[] link;
-+ /** The current table size. Note that an additional element is allocated for storing the null key. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the null key, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Creates a new hash set.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+
-+ public IntLinkedOpenHashSet( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new int[ n + 1 ];
-+  link = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 */
-+ public IntLinkedOpenHashSet( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public IntLinkedOpenHashSet() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c, final float f ) {
-+  this( c.size(), f );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 */
-+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c ) {
-+  this( c, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final IntCollection c, final float f ) {
-+  this( c.size(), f );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 */
-+ public IntLinkedOpenHashSet( final IntCollection c ) {
-+  this( c, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final IntIterator i, final float f ) {
-+  this( DEFAULT_INITIAL_SIZE, f );
-+  while( i.hasNext() ) add( i.nextInt() );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 */
-+ public IntLinkedOpenHashSet( final IntIterator i ) {
-+  this( i, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final Iterator<?> i, final float f ) {
-+  this( IntIterators.asIntIterator( i ), f );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 */
-+ public IntLinkedOpenHashSet( final Iterator<?> i ) {
-+  this( IntIterators.asIntIterator( i ) );
-+ }
-+ /** Creates a new hash set and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length, final float f ) {
-+  this( length < 0 ? 0 : length, f );
-+  IntArrays.ensureOffsetLength( a, offset, length );
-+  for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 */
-+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length ) {
-+  this( a, offset, length, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public IntLinkedOpenHashSet( final int[] a, final float f ) {
-+  this( a, 0, a.length, f );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 */
-+ public IntLinkedOpenHashSet( final int[] a ) {
-+  this( a, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNull ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( IntCollection c ) {
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( Collection<? extends Integer> c ) {
-+  // The resulting collection will be at least c.size() big
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ public boolean add( final int k ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) return false;
-+   pos = n;
-+   containsNull = true;
-+  }
-+  else {
-+   int curr;
-+   final int[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return false;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return false;
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  int curr;
-+  final int[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   fixPointers( pos, last );
-+  }
-+ }
-+ private boolean removeEntry( final int pos ) {
-+  size--;
-+  fixPointers( pos );
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+ private boolean removeNullEntry() {
-+  containsNull = false;
-+  key[ n ] = (0);
-+  size--;
-+  fixPointers( n );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+
-+ public boolean remove( final int k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) return removeNullEntry();
-+   return false;
-+  }
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+
-+ public boolean contains( final int k ) {
-+  if ( ( (k) == (0) ) ) return containsNull;
-+  int curr;
-+  final int[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ /** Removes the first key in iteration order.
-+	 * @return the first key.
-+	 * @throws NoSuchElementException is this set is empty.
-+	 */
-+ public int removeFirstInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = first;
-+  // Abbreviated version of fixPointers(pos)
-+  first = (int) link[ pos ];
-+  if ( 0 <= first ) {
-+   // Special case of SET_PREV( link[ first ], -1 )
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  final int k = key[ pos ];
-+  size--;
-+  if ( ( (k) == (0) ) ) {
-+   containsNull = false;
-+   key[ n ] = (0);
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return k;
-+ }
-+ /** Removes the the last key in iteration order.
-+	 * @return the last key.
-+	 * @throws NoSuchElementException is this set is empty.
-+	 */
-+ public int removeLastInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = last;
-+  // Abbreviated version of fixPointers(pos)
-+  last = (int) ( link[ pos ] >>> 32 );
-+  if ( 0 <= last ) {
-+   // Special case of SET_NEXT( link[ last ], -1 )
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  final int k = key[ pos ];
-+  size--;
-+  if ( ( (k) == (0) ) ) {
-+   containsNull = false;
-+   key[ n ] = (0);
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return k;
-+ }
-+ private void moveIndexToFirst( final int i ) {
-+  if ( size == 1 || first == i ) return;
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   // Special case of SET_NEXT( link[ last ], -1 );
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+  first = i;
-+ }
-+ private void moveIndexToLast( final int i ) {
-+  if ( size == 1 || last == i ) return;
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   // Special case of SET_PREV( link[ first ], -1 );
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+  last = i;
-+ }
-+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return true if the key was not present.
-+	 */
-+ public boolean addAndMoveToFirst( final int k ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) {
-+    moveIndexToFirst( n );
-+    return false;
-+   }
-+   containsNull = true;
-+   pos = n;
-+  }
-+  else {
-+   // The starting point.
-+   final int key[] = this.key;
-+   pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
-+   // There's always an unused entry. TODO
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( (k) == (key[ pos ]) ) ) {
-+     moveIndexToFirst( pos );
-+     return false;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+  }
-+  key[ pos ] = k;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+   first = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return true if the key was not present.
-+	 */
-+ public boolean addAndMoveToLast( final int k ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) {
-+    moveIndexToLast( n );
-+    return false;
-+   }
-+   containsNull = true;
-+   pos = n;
-+  }
-+  else {
-+   // The starting point.
-+   final int key[] = this.key;
-+   pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( (k) == (key[ pos ]) ) ) {
-+     moveIndexToLast( pos );
-+     return false;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+  }
-+  key[ pos ] = k;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /* Removes all elements from this set.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNull = false;
-+  Arrays.fill( key, (0) );
-+  first = last = -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** Modifies the {@link #link} vector so that the given entry is removed.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param i the index of an entry. 
-+	 */
-+ protected void fixPointers( final int i ) {
-+  if ( size == 0 ) {
-+   first = last = -1;
-+   return;
-+  }
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   if (0 <= first) {
-+    // Special case of SET_PREV( link[ first ], -1 )
-+    link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+   }
-+   return;
-+  }
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   if (0 <= last) {
-+    // Special case of SET_NEXT( link[ last ], -1 )
-+    link[ last ] |= -1 & 0xFFFFFFFFL;
-+   }
-+   return;
-+  }
-+  final long linki = link[ i ];
-+  final int prev = (int) ( linki >>> 32 );
-+  final int next = (int) linki;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+ }
-+ /** Modifies the {@link #link} vector for a shift from s to d.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param s the source position.
-+	 * @param d the destination position.
-+	 */
-+ protected void fixPointers( int s, int d ) {
-+  if ( size == 1 ) {
-+   first = last = d;
-+   // Special case of SET(link[ d ], -1, -1)
-+   link[ d ] = -1L;
-+   return;
-+  }
-+  if ( first == s ) {
-+   first = d;
-+   link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  if ( last == s ) {
-+   last = d;
-+   link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  final long links = link[ s ];
-+  final int prev = (int) ( links >>> 32 );
-+  final int next = (int) links;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ d ] = links;
-+ }
-+ /** Returns the first element of this set in iteration order.
-+	 *
-+	 * @return the first element in iteration order.
-+	 */
-+ public int firstInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ first ];
-+ }
-+ /** Returns the last element of this set in iteration order.
-+	 *
-+	 * @return the last element in iteration order.
-+	 */
-+ public int lastInt() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ last ];
-+ }
-+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
-+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
-+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
-+ public IntComparator comparator() { return null; }
-+ /** A list iterator over a linked set.
-+	 *
-+	 * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time. 
-+	 */
-+ private class SetIterator extends AbstractIntListIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  int prev = -1;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  int next = -1;
-+  /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
-+  int curr = -1;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
-+  int index = -1;
-+  SetIterator() {
-+   next = first;
-+   index = 0;
-+  }
-+  SetIterator( int from ) {
-+   if ( ( (from) == (0) ) ) {
-+    if ( IntLinkedOpenHashSet.this.containsNull ) {
-+     next = (int) link[ n ];
-+     prev = n;
-+     return;
-+    }
-+    else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
-+   }
-+   if ( ( (key[ last ]) == (from) ) ) {
-+    prev = last;
-+    index = size;
-+    return;
-+   }
-+   // The starting point.
-+   final int key[] = IntLinkedOpenHashSet.this.key;
-+   int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( (key[ pos ]) == (from) ) ) {
-+     // Note: no valid index known.
-+     next = (int) link[ pos ];
-+     prev = pos;
-+     return;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
-+  }
-+  public boolean hasNext() { return next != -1; }
-+  public boolean hasPrevious() { return prev != -1; }
-+  public int nextInt() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = next;
-+   next = (int) link[ curr ];
-+   prev = curr;
-+   if ( index >= 0 ) index++;
-+   if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
-+   return key[ curr ];
-+  }
-+  public int previousInt() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = prev;
-+   prev = (int) ( link[ curr ] >>> 32 );
-+   next = curr;
-+   if ( index >= 0 ) index--;
-+   return key[ curr ];
-+  }
-+  private final void ensureIndexKnown() {
-+   if ( index >= 0 ) return;
-+   if ( prev == -1 ) {
-+    index = 0;
-+    return;
-+   }
-+   if ( next == -1 ) {
-+    index = size;
-+    return;
-+   }
-+   int pos = first;
-+   index = 1;
-+   while( pos != prev ) {
-+    pos = (int) link[ pos ];
-+    index++;
-+   }
-+  }
-+  public int nextIndex() {
-+   ensureIndexKnown();
-+   return index;
-+  }
-+  public int previousIndex() {
-+   ensureIndexKnown();
-+   return index - 1;
-+  }
-+  public void remove() {
-+   ensureIndexKnown();
-+   if ( curr == -1 ) throw new IllegalStateException();
-+   if ( curr == prev ) {
-+    /* If the last operation was a next(), we are removing an entry that preceeds
-+				   the current index, and thus we must decrement it. */
-+    index--;
-+    prev = (int) ( link[ curr ] >>> 32 );
-+   }
-+   else
-+    next = (int) link[ curr ];
-+   size--;
-+   /* Now we manually fix the pointers. Because of our knowledge of next
-+			   and prev, this is going to be faster than calling fixPointers(). */
-+   if ( prev == -1 ) first = next;
-+   else
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   if ( next == -1 ) last = prev;
-+   else
-+    link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   int last, slot, pos = curr;
-+   curr = -1;
-+   if ( pos == n ) {
-+    IntLinkedOpenHashSet.this.containsNull = false;
-+    IntLinkedOpenHashSet.this.key[ n ] = (0);
-+   }
-+   else {
-+    int curr;
-+    final int[] key = IntLinkedOpenHashSet.this.key;
-+    // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.			
-+    for(;;) {
-+     pos = ( ( last = pos ) + 1 ) & mask;
-+     for(;;) {
-+      if ( ( (curr = key[ pos ]) == (0) ) ) {
-+       key[ last ] = (0);
-+       return;
-+      }
-+      slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
-+      if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+      pos = ( pos + 1 ) & mask;
-+     }
-+     key[ last ] = curr;
-+     if ( next == pos ) next = last;
-+     if ( prev == pos ) prev = last;
-+     fixPointers( pos, last );
-+    }
-+   }
-+  }
-+ }
-+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
-+	 * Please see the class documentation for implementation details.
-+	 *
-+	 * @param from an element to start from.
-+	 * @return a type-specific list iterator starting at the given element.
-+	 * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
-+	 */
-+ public IntListIterator iterator( int from ) {
-+  return new SetIterator( from );
-+ }
-+ public IntListIterator iterator() {
-+  return new SetIterator();
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes this set, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing.
-+	 *
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this set if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this set in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing sets.  {@linkplain #clear() Clearing a
-+	 * set} leaves the table size untouched. If you are reusing a set
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient sets.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the set.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+
-+ protected void rehash( final int newN ) {
-+  final int key[] = this.key;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final int newKey[] = new int[ newN + 1 ];
-+  int i = first, prev = -1, newPrev = -1, t, pos;
-+  final long link[] = this.link;
-+  final long newLink[] = new long[ newN + 1 ];
-+  first = -1;
-+  for( int j = size; j-- != 0; ) {
-+   if ( ( (key[ i ]) == (0) ) ) pos = newN;
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
-+    while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   newKey[ pos ] = key[ i ];
-+   if ( prev != -1 ) {
-+    newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    newPrev = pos;
-+   }
-+   else {
-+    newPrev = first = pos;
-+    // Special case of SET(newLink[ pos ], -1, -1);
-+    newLink[ pos ] = -1L;
-+   }
-+   t = i;
-+   i = (int) link[ i ];
-+   prev = t;
-+  }
-+  this.link = newLink;
-+  this.last = newPrev;
-+  if ( newPrev != -1 )
-+   // Special case of SET_NEXT( newLink[ newPrev ], -1 );
-+   newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public IntLinkedOpenHashSet clone() {
-+  IntLinkedOpenHashSet c;
-+  try {
-+   c = (IntLinkedOpenHashSet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.containsNull = containsNull;
-+  c.link = link.clone();
-+  return c;
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    h += (key[ i ]);
-+   i++;
-+  }
-+  // Zero / null have hash zero.		
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final IntIterator i = iterator();
-+  s.defaultWriteObject();
-+  for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final int key[] = this.key = new int[ n + 1 ];
-+  final long link[] = this.link = new long[ n + 1 ];
-+  int prev = -1;
-+  first = last = -1;
-+  int k;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readInt();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNull = true;
-+   }
-+   else {
-+    if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) )
-+     while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   }
-+   key[ pos ] = k;
-+   if ( first != -1 ) {
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    prev = pos;
-+   }
-+   else {
-+    prev = first = pos;
-+    // Special case of SET_PREV( newLink[ pos ], -1 );
-+    link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
-+   }
-+  }
-+  last = prev;
-+  if ( prev != -1 )
-+   // Special case of SET_NEXT( link[ prev ], -1 );
-+   link[ prev ] |= -1 & 0xFFFFFFFFL;
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.List;
-+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
-+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
-+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #listIterator()},
-+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
-+ *
-+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
-+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
-+ * of these methods, it is expected that concrete implementation override them with optimized versions.
-+ *
-+ * @see List
-+ */
-+public interface IntList extends List<Integer>, Comparable<List<? extends Integer>>, IntCollection {
-+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
-+	 *
-+	 * Note that this specification strengthens the one given in {@link List#iterator()}.
-+	 * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
-+	 * in {@link List}.
-+	 *
-+	 * @return an iterator on the elements of this list (in proper sequence).
-+	 */
-+ IntListIterator iterator();
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see #listIterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
-+	 */
-+ @Deprecated
-+ IntListIterator intListIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see #listIterator(int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
-+	 */
-+ @Deprecated
-+ IntListIterator intListIterator( int index );
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see List#listIterator()
-+	 */
-+ IntListIterator listIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see List#listIterator(int)
-+	 */
-+ IntListIterator listIterator( int index );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 * @see List#subList(int,int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
-+	 */
-+ @Deprecated
-+ IntList intSubList( int from, int to );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
-+	 *
-+	 * @see List#subList(int,int)
-+	 */
-+ IntList subList(int from, int to);
-+ /** Sets the size of this list.
-+	 *
-+	 * <P>If the specified size is smaller than the current size, the last elements are
-+	 * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
-+	 *
-+	 * @param size the new size.
-+	 */
-+ void size( int size );
-+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ void getElements( int from, int a[], int offset, int length );
-+ /** Removes (hopefully quickly) elements of this type-specific list.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ void removeElements( int from, int to );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 */
-+ void addElements( int index, int a[] );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ void addElements( int index, int a[], int offset, int length );
-+ /**
-+	 * @see List#add(Object)
-+	 */
-+ boolean add( int key );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ void add( int index, int key );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( int index, IntCollection c );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( int index, IntList c );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( IntList c );
-+ /**
-+	 * @see List#get(int)
-+	 */
-+ int getInt( int index );
-+ /**
-+	 * @see List#indexOf(Object)
-+	 */
-+ int indexOf( int k );
-+ /**
-+	 * @see List#lastIndexOf(Object)
-+	 */
-+ int lastIndexOf( int k );
-+ /**
-+	 * @see List#remove(int)
-+	 */
-+ int removeInt( int index );
-+ /**
-+	 * @see List#set(int,Object)
-+	 */
-+ int set( int index, int k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.ListIterator;
-+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
-+ *
-+ * <P>This interface merges the methods provided by a {@link ListIterator} and
-+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
-+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
-+ * and {@link java.util.ListIterator#set(Object) set()}.
-+ *
-+ * @see java.util.ListIterator
-+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
-+ */
-+public interface IntListIterator extends ListIterator<Integer>, IntBidirectionalIterator {
-+ void set( int k );
-+ void add( int k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.List;
-+import java.util.Collection;
-+import java.util.Random;
-+/** A class providing static methods and objects that do useful things with type-specific lists.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class IntLists {
-+ private IntLists() {}
-+ /** Shuffles the specified list using the specified pseudorandom number generator.
-+	 * 
-+	 * @param l the list to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>l</code>.
-+	 */
-+ public static IntList shuffle( final IntList l, final Random random ) {
-+  for( int i = l.size(); i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final int t = l.getInt( i );
-+   l.set( i, l.getInt( p ) );
-+   l.set( p, t );
-+  }
-+  return l;
-+ }
-+ /** An immutable class representing an empty type-specific list.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific list.
-+	 */
-+ public static class EmptyList extends IntCollections.EmptyCollection implements IntList , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyList() {}
-+  public void add( final int index, final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final int k ) { throw new UnsupportedOperationException(); }
-+  public int removeInt( int i ) { throw new UnsupportedOperationException(); }
-+  public int set( final int index, final int k ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( int k ) { return -1; }
-+  public int lastIndexOf( int k ) { return -1; }
-+  public boolean addAll( Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public Integer get( int i ) { throw new IndexOutOfBoundsException(); }
-+  public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( IntList c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, IntList c ) { throw new UnsupportedOperationException(); }
-+  public void add( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
-+  public Integer set( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
-+  public int getInt( int i ) { throw new IndexOutOfBoundsException(); }
-+  public Integer remove( int k ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( Object k ) { return -1; }
-+  public int lastIndexOf( Object k ) { return -1; }
-+  //SUPPRESS_WARNINGS_KEY_UNCHECKED
-+  //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
-+  @Deprecated
-+ 
-+  public IntIterator intIterator() { return IntIterators.EMPTY_ITERATOR; }
-+ 
-+  public IntListIterator listIterator() { return IntIterators.EMPTY_ITERATOR; }
-+ 
-+  public IntListIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
-+ 
-+  public IntListIterator listIterator( int i ) { if ( i == 0 ) return IntIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
-+  @Deprecated
-+  public IntListIterator intListIterator() { return listIterator(); }
-+  @Deprecated
-+  public IntListIterator intListIterator( int i ) { return listIterator( i ); }
-+  public IntList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
-+  @Deprecated
-+  public IntList intSubList( int from, int to ) { return subList( from, to ); }
-+  public void getElements( int from, int[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
-+  public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
-+  public void size( int s ) { throw new UnsupportedOperationException(); }
-+  public int compareTo( final List<? extends Integer> o ) {
-+   if ( o == this ) return 0;
-+   return ((List<?>)o).isEmpty() ? 0 : -1;
-+  }
-+  private Object readResolve() { return EMPTY_LIST; }
-+  public Object clone() { return EMPTY_LIST; }
-+  public int hashCode() { return 1; }
-+  @SuppressWarnings("rawtypes")
-+  public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
-+  public String toString() { return "[]"; }
-+ }
-+ /** An empty list (immutable). It is serializable and cloneable. 
-+	 */
-+
-+ public static final EmptyList EMPTY_LIST = new EmptyList();
-+ /** An immutable class representing a type-specific singleton list. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific list.
-+	 */
-+ public static class Singleton extends AbstractIntList implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  private final int element;
-+  private Singleton( final int element ) {
-+   this.element = element;
-+  }
-+  public int getInt( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
-+  public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final int k ) { return ( (k) == (element) ); }
-+  public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int i, final Collection <? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
-+  public int[] toIntArray() {
-+   int a[] = new int[ 1 ];
-+   a[ 0 ] = element;
-+   return a;
-+  }
-+  public IntListIterator listIterator() { return IntIterators.singleton( element ); }
-+  public IntListIterator iterator() { return listIterator(); }
-+  public IntListIterator listIterator( int i ) {
-+   if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
-+   IntListIterator l = listIterator();
-+   if ( i == 1 ) l.next();
-+   return l;
-+  }
-+ 
-+  public IntList subList( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+   if ( from != 0 || to != 1 ) return EMPTY_LIST;
-+   return this;
-+  }
-+  public int size() { return 1; }
-+  public void size( final int size ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public Object clone() { return this; }
-+  public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int i, final IntCollection c ) { throw new UnsupportedOperationException(); }
-+ }
-+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned list.
-+	 * @return a type-specific immutable list containing just <code>element</code>.
-+	 */
-+ public static IntList singleton( final int element ) { return new Singleton ( element ); }
-+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned list.
-+	 * @return a type-specific immutable list containing just <code>element</code>.
-+	 */
-+ public static IntList singleton( final Object element ) { return new Singleton ( ((((Integer)(element)).intValue())) ); }
-+ /** A synchronized wrapper class for lists. */
-+ public static class SynchronizedList extends IntCollections.SynchronizedCollection implements IntList , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
-+  protected SynchronizedList( final IntList l, final Object sync ) {
-+   super( l, sync );
-+   this.list = l;
-+  }
-+  protected SynchronizedList( final IntList l ) {
-+   super( l );
-+   this.list = l;
-+  }
-+  public int getInt( final int i ) { synchronized( sync ) { return list.getInt( i ); } }
-+  public int set( final int i, final int k ) { synchronized( sync ) { return list.set( i, k ); } }
-+  public void add( final int i, final int k ) { synchronized( sync ) { list.add( i, k ); } }
-+  public int removeInt( final int i ) { synchronized( sync ) { return list.removeInt( i ); } }
-+  public int indexOf( final int k ) { synchronized( sync ) { return list.indexOf( k ); } }
-+  public int lastIndexOf( final int k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
-+  public boolean addAll( final int index, final Collection<? extends Integer> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
-+  public void getElements( final int from, final int a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
-+  public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
-+  public void addElements( int index, final int a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
-+  public void addElements( int index, final int a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
-+  public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
-+  public IntListIterator iterator() { return list.listIterator(); }
-+  public IntListIterator listIterator() { return list.listIterator(); }
-+  public IntListIterator listIterator( final int i ) { return list.listIterator( i ); }
-+  @Deprecated
-+  public IntListIterator intListIterator() { return listIterator(); }
-+  @Deprecated
-+  public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
-+  public IntList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
-+  @Deprecated
-+  public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
-+  public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
-+  public int compareTo( final List<? extends Integer> o ) { synchronized( sync ) { return list.compareTo( o ); } }
-+  public boolean addAll( final int index, final IntCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
-+  public boolean addAll( final int index, IntList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
-+  public boolean addAll( IntList l ) { synchronized( sync ) { return list.addAll( l ); } }
-+  public Integer get( final int i ) { synchronized( sync ) { return list.get( i ); } }
-+  public void add( final int i, Integer k ) { synchronized( sync ) { list.add( i, k ); } }
-+  public Integer set( final int index, Integer k ) { synchronized( sync ) { return list.set( index, k ); } }
-+  public Integer remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
-+  public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
-+  public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
-+ }
-+ /** Returns a synchronized type-specific list backed by the given type-specific list.
-+	 *
-+	 * @param l the list to be wrapped in a synchronized list.
-+	 * @return a synchronized view of the specified list.
-+	 * @see java.util.Collections#synchronizedList(List)
-+	 */
-+ public static IntList synchronize( final IntList l ) { return new SynchronizedList ( l ); }
-+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
-+	 *
-+	 * @param l the list to be wrapped in a synchronized list.
-+	 * @param sync an object that will be used to synchronize the access to the list.
-+	 * @return a synchronized view of the specified list.
-+	 * @see java.util.Collections#synchronizedList(List)
-+	 */
-+ public static IntList synchronize( final IntList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
-+ /** An unmodifiable wrapper class for lists. */
-+ public static class UnmodifiableList extends IntCollections.UnmodifiableCollection implements IntList , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
-+  protected UnmodifiableList( final IntList l ) {
-+   super( l );
-+   this.list = l;
-+  }
-+  public int getInt( final int i ) { return list.getInt( i ); }
-+  public int set( final int i, final int k ) { throw new UnsupportedOperationException(); }
-+  public void add( final int i, final int k ) { throw new UnsupportedOperationException(); }
-+  public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( final int k ) { return list.indexOf( k ); }
-+  public int lastIndexOf( final int k ) { return list.lastIndexOf( k ); }
-+  public boolean addAll( final int index, final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public void getElements( final int from, final int a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
-+  public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
-+  public void size( final int size ) { list.size( size ); }
-+  public IntListIterator iterator() { return listIterator(); }
-+  public IntListIterator listIterator() { return IntIterators.unmodifiable( list.listIterator() ); }
-+  public IntListIterator listIterator( final int i ) { return IntIterators.unmodifiable( list.listIterator( i ) ); }
-+  @Deprecated
-+  public IntListIterator intListIterator() { return listIterator(); }
-+  @Deprecated
-+  public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
-+  public IntList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
-+  @Deprecated
-+  public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
-+  public boolean equals( final Object o ) { return collection.equals( o ); }
-+  public int hashCode() { return collection.hashCode(); }
-+  public int compareTo( final List<? extends Integer> o ) { return list.compareTo( o ); }
-+  public boolean addAll( final int index, final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final IntList l ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int index, final IntList l ) { throw new UnsupportedOperationException(); }
-+  public Integer get( final int i ) { return list.get( i ); }
-+  public void add( final int i, Integer k ) { throw new UnsupportedOperationException(); }
-+  public Integer set( final int index, Integer k ) { throw new UnsupportedOperationException(); }
-+  public Integer remove( final int i ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( final Object o ) { return list.indexOf( o ); }
-+  public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
-+ }
-+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
-+	 *
-+	 * @param l the list to be wrapped in an unmodifiable list.
-+	 * @return an unmodifiable view of the specified list.
-+	 * @see java.util.Collections#unmodifiableList(List)
-+	 */
-+ public static IntList unmodifiable( final IntList l ) { return new UnmodifiableList ( l ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.PriorityQueue;
-+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Additionally, this interface strengthens {@link #comparator()}.
-+ */
-+public interface IntPriorityQueue extends PriorityQueue<Integer> {
-+ /** Enqueues a new element.
-+	 *
-+	 * @param x the element to enqueue.
-+	 */
-+ void enqueue( int x );
-+ /** Dequeues the {@linkplain #first() first} element from the queue.
-+	 *
-+	 * @return the dequeued element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ int dequeueInt();
-+ /** Returns the first element of the queue.
-+	 *
-+	 * @return the first element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ int firstInt();
-+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
-+	 *
-+	 * @return the last element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ int lastInt();
-+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
-+	 *
-+	 * @see PriorityQueue#comparator()
-+	 */
-+ IntComparator comparator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+/** A class providing static methods and objects that do useful things with type-specific priority queues.
-+ *
-+ * @see it.unimi.dsi.fastutil.PriorityQueue
-+ */
-+public class IntPriorityQueues {
-+ private IntPriorityQueues() {}
-+ /** A synchronized wrapper class for priority queues. */
-+ public static class SynchronizedPriorityQueue implements IntPriorityQueue {
-+  final protected IntPriorityQueue q;
-+  final protected Object sync;
-+  protected SynchronizedPriorityQueue( final IntPriorityQueue q, final Object sync ) {
-+   this.q = q;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedPriorityQueue( final IntPriorityQueue q ) {
-+   this.q = q;
-+   this.sync = this;
-+  }
-+  public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
-+  public int dequeueInt() { synchronized( sync ) { return q.dequeueInt(); } }
-+  public int firstInt() { synchronized( sync ) { return q.firstInt(); } }
-+  public int lastInt() { synchronized( sync ) { return q.lastInt(); } }
-+  public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
-+  public int size() { synchronized( sync ) { return q.size(); } }
-+  public void clear() { synchronized( sync ) { q.clear(); } }
-+  public void changed() { synchronized( sync ) { q.changed(); } }
-+  public IntComparator comparator() { synchronized( sync ) { return q.comparator(); } }
-+  public void enqueue( Integer x ) { synchronized( sync ) { q.enqueue( x ); } }
-+  public Integer dequeue() { synchronized( sync ) { return q.dequeue(); } }
-+  public Integer first() { synchronized( sync ) { return q.first(); } }
-+  public Integer last() { synchronized( sync ) { return q.last(); } }
-+ }
-+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+ public static IntPriorityQueue synchronize( final IntPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
-+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @param sync an object that will be used to synchronize the access to the priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+ public static IntPriorityQueue synchronize( final IntPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+/** A class providing static methods and objects that do useful things with semi-indirect heaps.
-+ *
-+ * <P>A semi-indirect heap is based on a <em>reference array</em>. Elements of
-+ * a semi-indirect heap are integers that index the reference array (note that
-+ * in an <em>indirect</em> heap you can also map elements of the reference
-+ * array to heap positions).  
-+ */
-+public class IntSemiIndirectHeaps {
-+ private IntSemiIndirectHeaps() {}
-+ /** Moves the given element down into the semi-indirect heap until it reaches the lowest possible position.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param heap the semi-indirect heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index in the heap of the element to be moved down.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position in the heap of the element of heap index <code>i</code>.
-+	 */
-+
-+ public static int downHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  final int E = refArray[ e ];
-+  int child;
-+  if ( c == null )
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
-+    if ( ( (E) <= (refArray[ t ]) ) ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  else
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    int t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
-+    if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Moves the given element up in the semi-indirect heap until it reaches the highest possible position.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param heap the semi-indirect heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index in the heap of the element to be moved up.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position in the heap of the element of heap index <code>i</code>.
-+	 */
-+
-+ public static int upHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
-+  assert i < size;
-+  final int e = heap[ i ];
-+  final int E = refArray[ e ];
-+  if ( c == null )
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( ( (refArray[ t ]) <= (E) ) ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  else
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final int t = heap[ parent ];
-+    if ( c.compare( refArray[ t ], E ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Creates a semi-indirect heap in the given array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param offset the first element of the reference array to be put in the heap.
-+	 * @param length the number of elements to be put in the heap.
-+	 * @param heap the array where the heap is to be created.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final IntComparator c ) {
-+  IntArrays.ensureOffsetLength( refArray, offset, length );
-+  if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
-+  int i = length;
-+  while( i-- != 0 ) heap[ i ] = offset + i;
-+  i = length >>> 1;
-+  while( i-- != 0 ) downHeap( refArray, heap, length, i, c );
-+ }
-+ /** Creates a semi-indirect heap, allocating its heap array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param offset the first element of the reference array to be put in the heap.
-+	 * @param length the number of elements to be put in the heap.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the heap array.
-+	 */
-+ public static int[] makeHeap( final int[] refArray, final int offset, final int length, final IntComparator c ) {
-+  final int[] heap = length <= 0 ? IntArrays.EMPTY_ARRAY : new int[ length ];
-+  makeHeap( refArray, offset, length, heap, c );
-+  return heap;
-+ }
-+ /** Creates a semi-indirect heap from a given index array.
-+	 *
-+	 * @param refArray the reference array.
-+	 * @param heap an array containing indices into <code>refArray</code>.
-+	 * @param size the number of elements in the heap.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final int[] refArray, final int[] heap, final int size, final IntComparator c ) {
-+  int i = size >>> 1;
-+  while( i-- != 0 ) downHeap( refArray, heap, size, i, c );
-+ }
-+ /** Retrieves the front of a heap in a given array.
-+	 *
-+	 * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array 
-+	 * are equal to the element associated to the first index.
-+	 *
-+	 * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
-+	 * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that 
-+	 * terminates when all visited nodes are larger than the element associated
-+	 * to the top index, which implies that no elements of the front can be found later. 
-+	 * In most cases this trick yields a significant improvement.
-+	 * 
-+	 * @param refArray the reference array.
-+	 * @param heap an array containing indices into <code>refArray</code>.
-+	 * @param size the number of elements in the heap.
-+	 * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
-+	 * @return the number of elements actually written (starting from the first position of <code>a</code>).
-+	 */
-+
-+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a ) {
-+  final int top = refArray[ heap[ 0 ] ];
-+  int j = 0, // The current position in a
-+   l = 0, // The first position to visit in the next level (inclusive)
-+   r = 1, // The last position to visit in the next level (exclusive)
-+   f = 0; // The first position (in the heap array) of the next level
-+  for( int i = 0; i < r; i++ ) {
-+   if ( i == f ) { // New level
-+    if ( l >= r ) break; // If we are crossing the two bounds, we're over
-+    f = (f << 1) + 1; // Update the first position of the next level...
-+    i = l; // ...and jump directly to position l
-+    l = -1; // Invalidate l
-+   }
-+   if ( ( (top) == (refArray[ heap[ i ] ]) ) ) {
-+    a[ j++ ] = heap[ i ];
-+    if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
-+    r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
-+   }
-+  }
-+  return j;
-+ }
-+ /** Retrieves the front of a heap in a given array using a given comparator.
-+	 *
-+	 * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array 
-+	 * are equal to the element associated to the first index.
-+	 *
-+	 * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
-+	 * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that 
-+	 * terminates when all visited nodes are larger than the element associated
-+	 * to the top index, which implies that no elements of the front can be found later. 
-+	 * In most cases this trick yields a significant improvement.
-+	 * 
-+	 * @param refArray the reference array.
-+	 * @param heap an array containing indices into <code>refArray</code>.
-+	 * @param size the number of elements in the heap.
-+	 * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
-+	 * @param c a type-specific comparator.
-+	 * @return the number of elements actually written (starting from the first position of <code>a</code>).
-+	 */
-+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a, final IntComparator c ) {
-+  final int top = refArray[ heap[ 0 ] ];
-+  int j = 0, // The current position in a
-+   l = 0, // The first position to visit in the next level (inclusive)
-+   r = 1, // The last position to visit in the next level (exclusive)
-+   f = 0; // The first position (in the heap array) of the next level
-+  for( int i = 0; i < r; i++ ) {
-+   if ( i == f ) { // New level
-+    if ( l >= r ) break; // If we are crossing the two bounds, we're over
-+    f = (f << 1) + 1; // Update the first position of the next level...
-+    i = l; // ...and jump directly to position l
-+    l = -1; // Invalidate l
-+   }
-+   if ( c.compare( top, refArray[ heap[ i ] ] ) == 0 ) {
-+    a[ j++ ] = heap[ i ];
-+    if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
-+    r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
-+   }
-+  }
-+  return j;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Set;
-+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
-+ *
-+ * @see Set
-+ */
-+public interface IntSet extends IntCollection , Set<Integer> {
-+ /** Returns a type-specific iterator on the elements of this set.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
-+	 * which was already strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Set}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this set.
-+	 */
-+ IntIterator iterator();
-+ /** Removes an element from this set.
-+	 *
-+	 * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
-+	 * This unfortunate situation is caused by the clash
-+	 * with the similarly named index-based method in the {@link java.util.List} interface.
-+	 *
-+	 * @see java.util.Collection#remove(Object)
-+	 */
-+ public boolean remove( int k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.Collection;
-+import java.util.Set;
-+/** A class providing static methods and objects that do useful things with type-specific sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class IntSets {
-+ private IntSets() {}
-+ /** An immutable class representing the empty set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.
-+	 */
-+ public static class EmptySet extends IntCollections.EmptyCollection implements IntSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
-+  public Object clone() { return EMPTY_SET; }
-+  @SuppressWarnings("rawtypes")
-+  public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty set (immutable). It is serializable and cloneable.
-+	 */
-+
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** An immutable class representing a type-specific singleton set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.	 */
-+ public static class Singleton extends AbstractIntSet implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final int element;
-+  protected Singleton( final int element ) {
-+   this.element = element;
-+  }
-+  public boolean add( final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final int k ) { return ( (k) == (element) ); }
-+  public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
-+  public int[] toIntArray() {
-+   int a[] = new int[ 1 ];
-+   a[ 0 ] = element;
-+   return a;
-+  }
-+  public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
-+  public IntListIterator iterator() { return IntIterators.singleton( element ); }
-+  public int size() { return 1; }
-+  public Object clone() { return this; }
-+ }
-+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned set.
-+	 * @return a type-specific immutable set containing just <code>element</code>.
-+	 */
-+ public static IntSet singleton( final int element ) {
-+  return new Singleton ( element );
-+ }
-+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned set.
-+	 * @return a type-specific immutable set containing just <code>element</code>.
-+	 */
-+ public static IntSet singleton( final Integer element ) {
-+  return new Singleton ( ((element).intValue()) );
-+ }
-+ /** A synchronized wrapper class for sets. */
-+ public static class SynchronizedSet extends IntCollections.SynchronizedCollection implements IntSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected SynchronizedSet( final IntSet s, final Object sync ) {
-+   super( s, sync );
-+  }
-+  protected SynchronizedSet( final IntSet s ) {
-+   super( s );
-+  }
-+  public boolean remove( final int k ) { synchronized( sync ) { return collection.remove( (Integer.valueOf(k)) ); } }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
-+  public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
-+ }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static IntSet synchronize( final IntSet s ) { return new SynchronizedSet ( s ); }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @param sync an object that will be used to synchronize the access to the set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static IntSet synchronize( final IntSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
-+ /** An unmodifiable wrapper class for sets. */
-+ public static class UnmodifiableSet extends IntCollections.UnmodifiableCollection implements IntSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected UnmodifiableSet( final IntSet s ) {
-+   super( s );
-+  }
-+  public boolean remove( final int k ) { throw new UnsupportedOperationException(); }
-+  public boolean equals( final Object o ) { return collection.equals( o ); }
-+  public int hashCode() { return collection.hashCode(); }
-+ }
-+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in an unmodifiable set.
-+	 * @return an unmodifiable view of the specified set.
-+	 * @see java.util.Collections#unmodifiableSet(Set)
-+	 */
-+ public static IntSet unmodifiable( final IntSet s ) { return new UnmodifiableSet ( s ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.SortedSet;
-+import java.util.Collection;
-+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #iterator()},
-+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)}, 
-+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
-+ *
-+ * @see SortedSet
-+ */
-+public interface IntSortedSet extends IntSet , SortedSet<Integer> {
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set, starting from a given element of the domain (optional operation).
-+	 *
-+	 * <P>This method returns a type-specific bidirectional iterator with given
-+	 * starting point. The starting point is any element comparable to the
-+	 * elements of this set (even if it does not actually belong to the
-+	 * set). The next element of the returned iterator is the least element of
-+	 * the set that is greater than the starting point (if there are no
-+	 * elements greater than the starting point, {@link
-+	 * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
-+	 * <code>false</code>). The previous element of the returned iterator is
-+	 * the greatest element of the set that is smaller than or equal to the
-+	 * starting point (if there are no elements smaller than or equal to the
-+	 * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
-+	 * hasPrevious()} will return <code>false</code>).
-+	 *  
-+	 * <P>Note that passing the last element of the set as starting point and
-+	 * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
-+	 * entire set in reverse order.
-+	 *
-+	 * @param fromElement an element to start from.
-+	 * @return a bidirectional iterator on the element in this set, starting at the given element.
-+	 * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
-+	 */
-+ IntBidirectionalIterator iterator( int fromElement );
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
-+	 *
-+	 * <P>The iterator returned by the {@link #iterator()} method and by this
-+	 * method are identical; however, using this method you can save a type casting.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ IntBidirectionalIterator intIterator();
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set.
-+	 *
-+	 * <P>This method returns a parameterised bidirectional iterator. The iterator
-+	 * can be moreover safely cast to a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @return a bidirectional iterator on the element in this set. 
-+	 */
-+ IntBidirectionalIterator iterator();
-+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
-+	 *
-+	 * @see SortedSet#subSet(Object,Object)
-+	 */
-+ IntSortedSet subSet( Integer fromElement, Integer toElement) ;
-+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
-+	 *
-+	 * @see SortedSet#headSet(Object)
-+	 */
-+ IntSortedSet headSet( Integer toElement );
-+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
-+	 *
-+	 * @see SortedSet#tailSet(Object)
-+	 */
-+ IntSortedSet tailSet( Integer fromElement );
-+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
-+	 *
-+	 * @see SortedSet#comparator()
-+	 */
-+ IntComparator comparator();
-+ /**
-+	 * @see SortedSet#subSet(Object,Object)
-+	 */
-+ IntSortedSet subSet( int fromElement, int toElement) ;
-+ /**
-+	 * @see SortedSet#headSet(Object)
-+	 */
-+ IntSortedSet headSet( int toElement );
-+ /**
-+	 * @see SortedSet#tailSet(Object)
-+	 */
-+ IntSortedSet tailSet( int fromElement );
-+ /**
-+	 * @see SortedSet#first()
-+	 */
-+ int firstInt();
-+ /**
-+	 * @see SortedSet#last()
-+	 */
-+ int lastInt();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import java.util.SortedSet;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class IntSortedSets {
-+ private IntSortedSets() {}
-+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class EmptySet extends IntSets.EmptySet implements IntSortedSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
-+  @Deprecated
-+  public IntBidirectionalIterator intIterator() { return iterator(); }
-+ 
-+  public IntBidirectionalIterator iterator( int from ) { return IntIterators.EMPTY_ITERATOR; }
-+ 
-+  public IntSortedSet subSet( int from, int to ) { return EMPTY_SET; }
-+ 
-+  public IntSortedSet headSet( int from ) { return EMPTY_SET; }
-+ 
-+  public IntSortedSet tailSet( int to ) { return EMPTY_SET; }
-+  public int firstInt() { throw new NoSuchElementException(); }
-+  public int lastInt() { throw new NoSuchElementException(); }
-+  public IntComparator comparator() { return null; }
-+  public IntSortedSet subSet( Integer from, Integer to ) { return EMPTY_SET; }
-+  public IntSortedSet headSet( Integer from ) { return EMPTY_SET; }
-+  public IntSortedSet tailSet( Integer to ) { return EMPTY_SET; }
-+  public Integer first() { throw new NoSuchElementException(); }
-+  public Integer last() { throw new NoSuchElementException(); }
-+  public Object clone() { return EMPTY_SET; }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty sorted set (immutable). It is serializable and cloneable.
-+	 *
-+	 */
-+
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** A class representing a singleton sorted set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class Singleton extends IntSets.Singleton implements IntSortedSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  final IntComparator comparator;
-+  private Singleton( final int element, final IntComparator comparator ) {
-+   super( element );
-+   this.comparator = comparator;
-+  }
-+  private Singleton( final int element ) {
-+   this( element, null );
-+  }
-+ 
-+  final int compare( final int k1, final int k2 ) {
-+   return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
-+  }
-+  @Deprecated
-+  public IntBidirectionalIterator intIterator() {
-+   return iterator();
-+  }
-+  public IntBidirectionalIterator iterator( int from ) {
-+   IntBidirectionalIterator i = iterator();
-+   if ( compare( element, from ) <= 0 ) i.next();
-+   return i;
-+  }
-+  public IntComparator comparator() { return comparator; }
-+ 
-+  public IntSortedSet subSet( final int from, final int to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+ 
-+  public IntSortedSet headSet( final int to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+ 
-+  public IntSortedSet tailSet( final int from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
-+  public int firstInt() { return element; }
-+  public int lastInt() { return element; }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer first() { return (Integer.valueOf(element)); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Integer last() { return (Integer.valueOf(element)); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public IntSortedSet subSet( final Integer from, final Integer to ) { return subSet( ((from).intValue()), ((to).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public IntSortedSet headSet( final Integer to ) { return headSet( ((to).intValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public IntSortedSet tailSet( final Integer from ) { return tailSet( ((from).intValue()) ); }
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static IntSortedSet singleton( final int element ) {
-+  return new Singleton ( element );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @param comparator the comparator to use in the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static IntSortedSet singleton( final int element, final IntComparator comparator ) {
-+  return new Singleton ( element, comparator );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static IntSortedSet singleton( final Object element ) {
-+  return new Singleton( ((((Integer)(element)).intValue())) );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @param comparator the comparator to use in the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static IntSortedSet singleton( final Object element, final IntComparator comparator ) {
-+  return new Singleton( ((((Integer)(element)).intValue())), comparator );
-+ }
-+ /** A synchronized wrapper class for sorted sets. */
-+ public static class SynchronizedSortedSet extends IntSets.SynchronizedSet implements IntSortedSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntSortedSet sortedSet;
-+  protected SynchronizedSortedSet( final IntSortedSet s, final Object sync ) {
-+   super( s, sync );
-+   sortedSet = s;
-+  }
-+  protected SynchronizedSortedSet( final IntSortedSet s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public IntComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
-+  public IntSortedSet subSet( final int from, final int to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
-+  public IntSortedSet headSet( final int to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
-+  public IntSortedSet tailSet( final int from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
-+  public IntBidirectionalIterator iterator() { return sortedSet.iterator(); }
-+  public IntBidirectionalIterator iterator( final int from ) { return sortedSet.iterator( from ); }
-+  @Deprecated
-+  public IntBidirectionalIterator intIterator() { return sortedSet.iterator(); }
-+  public int firstInt() { synchronized( sync ) { return sortedSet.firstInt(); } }
-+  public int lastInt() { synchronized( sync ) { return sortedSet.lastInt(); } }
-+  public Integer first() { synchronized( sync ) { return sortedSet.first(); } }
-+  public Integer last() { synchronized( sync ) { return sortedSet.last(); } }
-+  public IntSortedSet subSet( final Integer from, final Integer to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
-+  public IntSortedSet headSet( final Integer to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
-+  public IntSortedSet tailSet( final Integer from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
-+ }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static IntSortedSet synchronize( final IntSortedSet s ) { return new SynchronizedSortedSet ( s ); }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @param sync an object that will be used to synchronize the access to the sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static IntSortedSet synchronize( final IntSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
-+ /** An unmodifiable wrapper class for sorted sets. */
-+ public static class UnmodifiableSortedSet extends IntSets.UnmodifiableSet implements IntSortedSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final IntSortedSet sortedSet;
-+  protected UnmodifiableSortedSet( final IntSortedSet s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public IntComparator comparator() { return sortedSet.comparator(); }
-+  public IntSortedSet subSet( final int from, final int to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
-+  public IntSortedSet headSet( final int to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
-+  public IntSortedSet tailSet( final int from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
-+  public IntBidirectionalIterator iterator() { return IntIterators.unmodifiable( sortedSet.iterator() ); }
-+  public IntBidirectionalIterator iterator( final int from ) { return IntIterators.unmodifiable( sortedSet.iterator( from ) ); }
-+  @Deprecated
-+  public IntBidirectionalIterator intIterator() { return iterator(); }
-+  public int firstInt() { return sortedSet.firstInt(); }
-+  public int lastInt() { return sortedSet.lastInt(); }
-+  public Integer first() { return sortedSet.first(); }
-+  public Integer last() { return sortedSet.last(); }
-+  public IntSortedSet subSet( final Integer from, final Integer to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
-+  public IntSortedSet headSet( final Integer to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
-+  public IntSortedSet tailSet( final Integer from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
-+ }
-+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in an unmodifiable sorted set.
-+	 * @return an unmodifiable view of the specified sorted set.
-+	 * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
-+	 */
-+ public static IntSortedSet unmodifiable( final IntSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.ints;
-+import it.unimi.dsi.fastutil.Stack;
-+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ */
-+public interface IntStack extends Stack<Integer> {
-+ /**
-+	 * @see Stack#push(Object)
-+	 */
-+ void push( int k );
-+ /**
-+	 * @see Stack#pop()
-+	 */
-+ int popInt();
-+ /** 
-+	 * @see Stack#top()
-+	 */
-+ int topInt();
-+ /** 
-+	 * @see Stack#peek(int)
-+	 */
-+ int peekInt( int i );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/package.html b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
-@@ -0,0 +0,0 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-+<html>
-+  <head>
-+    <title>fastutil</title>
-+  </head>
-+
-+  <body>
-+
-+	 <P>Provides type-specific classes for integer elements or keys.
-+
-+  </body>
-+</html>
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** An abstract class providing basic methods for functions implementing a type-specific interface.
-+ *
-+ * <P>Optional operations just throw an {@link
-+ * UnsupportedOperationException}. Generic versions of accessors delegate to
-+ * the corresponding type-specific counterparts following the interface rules
-+ * (they take care of returning <code>null</code> on a missing key).
-+ *
-+ * <P>This class handles directly a default return
-+ * value (including {@linkplain #defaultReturnValue() methods to access
-+ * it}). Instances of classes inheriting from this class have just to return
-+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
-+ * is serialized.
-+ *
-+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
-+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
-+ *
-+ */
-+public abstract class AbstractLong2ObjectFunction <V> implements Long2ObjectFunction <V>, java.io.Serializable {
-+ private static final long serialVersionUID = -4940583368468432370L;
-+ protected AbstractLong2ObjectFunction() {}
-+ /**
-+	 * The default return value for <code>get()</code>, <code>put()</code> and
-+	 * <code>remove()</code>.  
-+	 */
-+ protected V defRetValue;
-+ public void defaultReturnValue( final V rv ) {
-+  defRetValue = rv;
-+ }
-+ public V defaultReturnValue() {
-+  return defRetValue;
-+ }
-+ public V put( long key, V value ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public V remove( long key ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public void clear() {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean containsKey( final Object ok ) {
-+  if ( ok == null ) return false;
-+  return containsKey( ((((Long)(ok)).longValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 */
-+ public V get( final Object ok ) {
-+  if ( ok == null ) return null;
-+  final long k = ((((Long)(ok)).longValue()));
-+  return containsKey( k ) ? (get( k )) : null;
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key. 
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 *
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V put( final Long ok, final V ov ) {
-+  final long k = ((ok).longValue());
-+  final boolean containsKey = containsKey( k );
-+  final V v = put( k, (ov) );
-+  return containsKey ? (v) : null;
-+ }
-+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key. 
-+	 *
-+	 * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
-+	 * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
-+	 */
-+ public V remove( final Object ok ) {
-+  if ( ok == null ) return null;
-+  final long k = ((((Long)(ok)).longValue()));
-+  final boolean containsKey = containsKey( k );
-+  final V v = remove( k );
-+  return containsKey ? (v) : null;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import java.util.Iterator;
-+import java.util.Map;
-+/** An abstract class providing basic methods for maps implementing a type-specific interface.
-+ *
-+ * <P>Optional operations just throw an {@link
-+ * UnsupportedOperationException}. Generic versions of accessors delegate to
-+ * the corresponding type-specific counterparts following the interface rules
-+ * (they take care of returning <code>null</code> on a missing key).
-+ *
-+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
-+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
-+ * is particularly useful for those classes that do not implement their own
-+ * entries (e.g., most immutable maps).
-+ */
-+public abstract class AbstractLong2ObjectMap <V> extends AbstractLong2ObjectFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
-+ private static final long serialVersionUID = -4940583368468432370L;
-+ protected AbstractLong2ObjectMap() {}
-+ /** Checks whether the given value is contained in {@link #values()}. */
-+ public boolean containsValue( Object v ) {
-+  return values().contains( v );
-+ }
-+ /** Checks whether the given value is contained in {@link #keySet()}. */
-+ public boolean containsKey( long k ) {
-+  return keySet().contains( k );
-+ }
-+ /** Puts all pairs in the given map.
-+	 * If the map implements the interface of this map,
-+	 * it uses the faster iterators.
-+	 *
-+	 * @param m a map.
-+	 */
-+  @SuppressWarnings({"unchecked","deprecation"})
-+ public void putAll(Map<? extends Long,? extends V> m) {
-+  int n = m.size();
-+  final Iterator<? extends Map.Entry<? extends Long,? extends V>> i = m.entrySet().iterator();
-+  if (m instanceof Long2ObjectMap) {
-+   Long2ObjectMap.Entry <? extends V> e;
-+   while(n-- != 0) {
-+    e = (Long2ObjectMap.Entry <? extends V>)i.next();
-+    put(e.getLongKey(), e.getValue());
-+   }
-+  }
-+  else {
-+   Map.Entry<? extends Long,? extends V> e;
-+   while(n-- != 0) {
-+    e = i.next();
-+    put(e.getKey(), e.getValue());
-+   }
-+  }
-+ }
-+ public boolean isEmpty() {
-+  return size() == 0;
-+ }
-+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
-+	 * that do not have entries on their own (e.g., most immutable maps). 
-+	 *
-+	 * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
-+	 * would not be reflected in the base map.
-+	 */
-+ public static class BasicEntry <V> implements Long2ObjectMap.Entry <V> {
-+  protected long key;
-+  protected V value;
-+  public BasicEntry( final Long key, final V value ) {
-+   this.key = ((key).longValue());
-+   this.value = (value);
-+  }
-+  public BasicEntry( final long key, final V value ) {
-+   this.key = key;
-+   this.value = value;
-+  }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long getKey() {
-+   return (Long.valueOf(key));
-+  }
-+  public long getLongKey() {
-+   return key;
-+  }
-+  public V getValue() {
-+   return (value);
-+  }
-+  public V setValue( final V value ) {
-+   throw new UnsupportedOperationException();
-+  }
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-+   return ( (key) == (((((Long)(e.getKey())).longValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() );
-+  }
-+  public String toString() {
-+   return key + "->" + value;
-+  }
-+ }
-+ /** Returns a type-specific-set view of the keys of this map.
-+	 *
-+	 * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public LongSet keySet() {
-+  return new AbstractLongSet () {
-+    public boolean contains( final long k ) { return containsKey( k ); }
-+    public int size() { return AbstractLong2ObjectMap.this.size(); }
-+    public void clear() { AbstractLong2ObjectMap.this.clear(); }
-+    public LongIterator iterator() {
-+     return new AbstractLongIterator () {
-+       final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
-+       /** {@inheritDoc}
-+							 * @deprecated Please use the corresponding type-specific method instead. */
-+       @Deprecated
-+       public long nextLong() { return ((Long2ObjectMap.Entry <V>)i.next()).getLongKey(); };
-+       public boolean hasNext() { return i.hasNext(); }
-+      };
-+    }
-+   };
-+ }
-+ /** Returns a type-specific-set view of the values of this map.
-+	 *
-+	 * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public ObjectCollection <V> values() {
-+  return new AbstractObjectCollection <V>() {
-+    public boolean contains( final Object k ) { return containsValue( k ); }
-+    public int size() { return AbstractLong2ObjectMap.this.size(); }
-+    public void clear() { AbstractLong2ObjectMap.this.clear(); }
-+    public ObjectIterator <V> iterator() {
-+     return new AbstractObjectIterator <V>() {
-+       final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
-+       /** {@inheritDoc}
-+							 * @deprecated Please use the corresponding type-specific method instead. */
-+       @Deprecated
-+       public V next() { return ((Long2ObjectMap.Entry <V>)i.next()).getValue(); };
-+       public boolean hasNext() { return i.hasNext(); }
-+      };
-+    }
-+   };
-+ }
-+ @SuppressWarnings({ "unchecked", "rawtypes" })
-+ public ObjectSet<Map.Entry<Long, V>> entrySet() {
-+  return (ObjectSet)long2ObjectEntrySet();
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * The hash code of a map is computed by summing the hash codes of its entries.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0, n = size();
-+  final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
-+  while( n-- != 0 ) h += i.next().hashCode();
-+  return h;
-+ }
-+ public boolean equals(Object o) {
-+  if ( o == this ) return true;
-+  if ( ! ( o instanceof Map ) ) return false;
-+  Map<?,?> m = (Map<?,?>)o;
-+  if ( m.size() != size() ) return false;
-+  return entrySet().containsAll( m.entrySet() );
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
-+  int n = size();
-+  Long2ObjectMap.Entry <V> e;
-+  boolean first = true;
-+  s.append("{");
-+  while(n-- != 0) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   e = (Long2ObjectMap.Entry <V>)i.next();
-+    s.append(String.valueOf(e.getLongKey()));
-+   s.append("=>");
-+   if (this == e.getValue()) s.append("(this map)"); else
-+    s.append(String.valueOf(e.getValue()));
-+  }
-+  s.append("}");
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import java.util.Map;
-+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
-+public abstract class AbstractLong2ObjectSortedMap <V> extends AbstractLong2ObjectMap <V> implements Long2ObjectSortedMap <V> {
-+ private static final long serialVersionUID = -1773560792952436569L;
-+ protected AbstractLong2ObjectSortedMap() {}
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long2ObjectSortedMap <V> headMap( final Long to ) {
-+  return headMap( ((to).longValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long2ObjectSortedMap <V> tailMap( final Long from ) {
-+  return tailMap( ((from).longValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) {
-+  return subMap( ((from).longValue()), ((to).longValue()) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long firstKey() {
-+  return (Long.valueOf(firstLongKey()));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long lastKey() {
-+  return (Long.valueOf(lastLongKey()));
-+ }
-+ /** Returns a type-specific-sorted-set view of the keys of this map.
-+	 *
-+	 * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
-+	 */
-+ public LongSortedSet keySet() {
-+  return new KeySet();
-+ }
-+ /** A wrapper exhibiting the keys of a map. */
-+ protected class KeySet extends AbstractLongSortedSet {
-+  public boolean contains( final long k ) { return containsKey( k ); }
-+  public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
-+  public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
-+  public LongComparator comparator() { return AbstractLong2ObjectSortedMap.this.comparator(); }
-+  public long firstLong() { return firstLongKey(); }
-+  public long lastLong() { return lastLongKey(); }
-+  public LongSortedSet headSet( final long to ) { return headMap( to ).keySet(); }
-+  public LongSortedSet tailSet( final long from ) { return tailMap( from ).keySet(); }
-+  public LongSortedSet subSet( final long from, final long to ) { return subMap( from, to ).keySet(); }
-+  public LongBidirectionalIterator iterator( final long from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
-+  public LongBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
-+ }
-+ /** A wrapper exhibiting a map iterator as an iterator on keys.
-+	 *
-+	 * <P>To provide an iterator on keys, just create an instance of this
-+	 * class using the corresponding iterator on entries.
-+	 */
-+ protected static class KeySetIterator <V> extends AbstractLongBidirectionalIterator {
-+  protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
-+  public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
-+   this.i = i;
-+  }
-+  public long nextLong() { return ((i.next().getKey()).longValue()); };
-+  public long previousLong() { return ((i.previous().getKey()).longValue()); };
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+ }
-+ /** Returns a type-specific collection view of the values contained in this map.
-+	 *
-+	 * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
-+	 * <em>no attempt is made at caching the result of this method</em>, as this would
-+	 * require adding some attributes that lightweight implementations would
-+	 * not need. Subclasses may easily override this policy by calling
-+	 * this method and caching the result, but implementors are encouraged to
-+	 * write more efficient ad-hoc implementations.
-+	 *
-+	 * @return a type-specific collection view of the values contained in this map.
-+	 */
-+ public ObjectCollection <V> values() {
-+  return new ValuesCollection();
-+ }
-+ /** A wrapper exhibiting the values of a map. */
-+ protected class ValuesCollection extends AbstractObjectCollection <V> {
-+  public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
-+  public boolean contains( final Object k ) { return containsValue( k ); }
-+  public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
-+  public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
-+ }
-+ /** A wrapper exhibiting a map iterator as an iterator on values.
-+	 *
-+	 * <P>To provide an iterator on values, just create an instance of this
-+	 * class using the corresponding iterator on entries.
-+	 */
-+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
-+  protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
-+  public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
-+   this.i = i;
-+  }
-+  public V next() { return (i.next().getValue()); };
-+  public boolean hasNext() { return i.hasNext(); }
-+ }
-+ @SuppressWarnings({ "unchecked", "rawtypes" })
-+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() {
-+  return (ObjectSortedSet)long2ObjectEntrySet();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
-+ *
-+ * <P>To create a type-specific bidirectional iterator, besides what is needed
-+ * for an iterator you need both a method returning the previous element as
-+ * primitive type and a method returning the previous element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #back(int)} that
-+ * uses type-specific methods.
-+ */
-+public abstract class AbstractLongBidirectionalIterator extends AbstractLongIterator implements LongBidirectionalIterator {
-+ protected AbstractLongBidirectionalIterator() {}
-+ /** Delegates to the corresponding generic method. */
-+ public long previousLong() { return previous().longValue(); }
-+ /** Delegates to the corresponding type-specific method. */
-+ public Long previous() { return Long.valueOf( previousLong() ); }
-+ /** This method just iterates the type-specific version of {@link #previous()} for
-+	 * at most <code>n</code> times, stopping if {@link
-+	 * #hasPrevious()} becomes false. */
-+ public int back( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasPrevious() ) previousLong();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.AbstractCollection;
-+import java.util.Collection;
-+import java.util.Iterator;
-+/** An abstract class providing basic methods for collections implementing a type-specific interface.
-+ *
-+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
-+ * {@link #contains(Object)} methods that just call the type-specific counterpart. 
-+ */
-+public abstract class AbstractLongCollection extends AbstractCollection<Long> implements LongCollection {
-+ protected AbstractLongCollection() {}
-+ public long[] toArray( long a[] ) {
-+  return toLongArray( a );
-+ }
-+ public long[] toLongArray() {
-+  return toLongArray( null );
-+ }
-+ public long[] toLongArray( long a[] ) {
-+  if ( a == null || a.length < size() ) a = new long[ size() ];
-+  LongIterators.unwrap( iterator(), a );
-+  return a;
-+ }
-+ /** Adds all elements of the given type-specific collection to this collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean addAll( LongCollection c ) {
-+  boolean retVal = false;
-+  final LongIterator i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( add( i.nextLong() ) ) retVal = true;
-+  return retVal;
-+ }
-+ /** Checks whether this collection contains all elements from the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection contains all elements of the argument.
-+	 */
-+ public boolean containsAll( LongCollection c ) {
-+  final LongIterator i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( ! contains( i.nextLong() ) ) return false;
-+  return true;
-+ }
-+ /** Retains in this collection only elements from the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean retainAll( LongCollection c ) {
-+  boolean retVal = false;
-+  int n = size();
-+  final LongIterator i = iterator();
-+  while( n-- != 0 ) {
-+   if ( ! c.contains( i.nextLong() ) ) {
-+    i.remove();
-+    retVal = true;
-+   }
-+  }
-+  return retVal;
-+ }
-+ /** Remove from this collection all elements in the given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean removeAll( LongCollection c ) {
-+  boolean retVal = false;
-+  int n = c.size();
-+  final LongIterator i = c.iterator();
-+  while( n-- != 0 ) if ( rem( i.nextLong() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public Object[] toArray() {
-+  final Object[] a = new Object[ size() ];
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  return a;
-+ }
-+ @SuppressWarnings("unchecked")
-+ public <T> T[] toArray( T[] a ) {
-+  final int size = size();
-+  if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  if ( size < a.length ) a[ size ] = null;
-+  return a;
-+ }
-+ /** Adds all elements of the given collection to this collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean addAll( Collection<? extends Long> c ) {
-+  boolean retVal = false;
-+  final Iterator<? extends Long> i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean add( long k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public LongIterator longIterator() {
-+  return iterator();
-+ }
-+ public abstract LongIterator iterator();
-+ /** Delegates to the type-specific <code>rem()</code> method. */
-+ public boolean remove( Object ok ) {
-+  if ( ok == null ) return false;
-+  return rem( ((((Long)(ok)).longValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean add( final Long o ) {
-+  return add( o.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean rem( final Object o ) {
-+  if ( o == null ) return false;
-+  return rem( ((((Long)(o)).longValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean contains( final Object o ) {
-+  if ( o == null ) return false;
-+  return contains( ((((Long)(o)).longValue())) );
-+ }
-+ public boolean contains( final long k ) {
-+  final LongIterator iterator = iterator();
-+  while ( iterator.hasNext() ) if ( k == iterator.nextLong() ) return true;
-+        return false;
-+    }
-+ public boolean rem( final long k ) {
-+  final LongIterator iterator = iterator();
-+  while ( iterator.hasNext() )
-+   if ( k == iterator.nextLong() ) {
-+    iterator.remove();
-+    return true;
-+   }
-+        return false;
-+    }
-+ /** Checks whether this collection contains all elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection contains all elements of the argument.
-+	 */
-+ public boolean containsAll( Collection<?> c ) {
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
-+  return true;
-+ }
-+ /** Retains in this collection only elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean retainAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = size();
-+  final Iterator<?> i = iterator();
-+  while( n-- != 0 ) {
-+   if ( ! c.contains( i.next() ) ) {
-+    i.remove();
-+    retVal = true;
-+   }
-+  }
-+  return retVal;
-+ }
-+ /** Remove from this collection all elements in the given collection.
-+	 * If the collection is an instance of this class, it uses faster iterators.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean removeAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean isEmpty() {
-+  return size() == 0;
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final LongIterator i = iterator();
-+  int n = size();
-+  long k;
-+  boolean first = true;
-+  s.append("{");
-+  while(n-- != 0) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.nextLong();
-+    s.append(String.valueOf(k));
-+  }
-+  s.append("}");
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
-+ *
-+ * <P>To create a type-specific comparator you need both a method comparing
-+ * primitive types and a method comparing objects. However, if you have the
-+ * first one you can just inherit from this class and get for free the second
-+ * one.
-+ * 
-+ * @see java.util.Comparator
-+ */
-+public abstract class AbstractLongComparator implements LongComparator , java.io.Serializable {
-+    private static final long serialVersionUID = 0L;
-+ protected AbstractLongComparator() {}
-+ public int compare( Long ok1, Long ok2 ) {
-+  return compare( ok1.longValue(), ok2.longValue() );
-+ }
-+ public abstract int compare( long k1, long k2 );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/**  An abstract class facilitating the creation of type-specific iterators.
-+ *
-+ * <P>To create a type-specific iterator you need both a method returning the
-+ * next element as primitive type and a method returning the next element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
-+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
-+ * UnsupportedOperationException}.
-+ *
-+ * @see java.util.Iterator
-+ */
-+public abstract class AbstractLongIterator implements LongIterator {
-+ protected AbstractLongIterator() {}
-+ /** Delegates to the corresponding generic method. */
-+ public long nextLong() { return next().longValue(); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long next() { return Long.valueOf( nextLong() ); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void remove() { throw new UnsupportedOperationException(); }
-+ /** This method just iterates the type-specific version of {@link #next()} for at most
-+	 * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
-+ public int skip( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasNext() ) nextLong();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.List;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/**  An abstract class providing basic methods for lists implementing a type-specific list interface.
-+ *
-+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
-+ */
-+public abstract class AbstractLongList extends AbstractLongCollection implements LongList , LongStack {
-+ protected AbstractLongList() {}
-+ /** Ensures that the given index is nonnegative and not greater than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
-+	 */
-+ protected void ensureIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
-+ }
-+ /** Ensures that the given index is nonnegative and smaller than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
-+	 */
-+ protected void ensureRestrictedIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
-+ }
-+ public void add( final int index, final long k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean add( final long k ) {
-+  add( size(), k );
-+  return true;
-+ }
-+ public long removeLong( int i ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public long set( final int index, final long k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean addAll( int index, final Collection<? extends Long> c ) {
-+  ensureIndex( index );
-+  int n = c.size();
-+  if ( n == 0 ) return false;
-+  Iterator<? extends Long> i = c.iterator();
-+  while( n-- != 0 ) add( index++, i.next() );
-+  return true;
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final Collection<? extends Long> c ) {
-+  return addAll( size(), c );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public LongListIterator longListIterator() {
-+  return listIterator();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public LongListIterator longListIterator( final int index ) {
-+  return listIterator( index );
-+ }
-+ public LongListIterator iterator() {
-+  return listIterator();
-+ }
-+ public LongListIterator listIterator() {
-+  return listIterator( 0 );
-+ }
-+ public LongListIterator listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractLongListIterator () {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < AbstractLongList.this.size(); }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = pos++ ); }
-+    public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = --pos ); }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( long k ) {
-+     AbstractLongList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( long k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractLongList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractLongList.this.removeLong( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public boolean contains( final long k ) {
-+  return indexOf( k ) >= 0;
-+ }
-+ public int indexOf( final long k ) {
-+  final LongListIterator i = listIterator();
-+  long e;
-+  while( i.hasNext() ) {
-+   e = i.nextLong();
-+   if ( ( (k) == (e) ) ) return i.previousIndex();
-+  }
-+  return -1;
-+ }
-+ public int lastIndexOf( final long k ) {
-+  LongListIterator i = listIterator( size() );
-+  long e;
-+  while( i.hasPrevious() ) {
-+   e = i.previousLong();
-+   if ( ( (k) == (e) ) ) return i.nextIndex();
-+  }
-+  return -1;
-+ }
-+ public void size( final int size ) {
-+  int i = size();
-+  if ( size > i ) while( i++ < size ) add( (0) );
-+  else while( i-- != size ) remove( i );
-+ }
-+ public LongList subList( final int from, final int to ) {
-+  ensureIndex( from );
-+  ensureIndex( to );
-+  if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  return new LongSubList ( this, from, to );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public LongList longSubList( final int from, final int to ) {
-+  return subList( from, to );
-+ }
-+ /** Removes elements of this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  ensureIndex( to );
-+  LongListIterator i = listIterator( from );
-+  int n = to - from;
-+  if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  while( n-- != 0 ) {
-+   i.nextLong();
-+   i.remove();
-+  }
-+ }
-+ /** Adds elements to this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( int index, final long a[], int offset, int length ) {
-+  ensureIndex( index );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  while( length-- != 0 ) add( index++, a[ offset++ ] );
-+ }
-+ public void addElements( final int index, final long a[] ) {
-+  addElements( index, a, 0, a.length );
-+ }
-+ /** Copies element of this type-specific list into the given array one-by-one.
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final long a[], int offset, int length ) {
-+  LongListIterator i = listIterator( from );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
-+  while( length-- != 0 ) a[ offset++ ] = i.nextLong();
-+ }
-+ private boolean valEquals( final Object a, final Object b ) {
-+  return a == null ? b == null : a.equals( b );
-+ }
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( ! ( o instanceof List ) ) return false;
-+  final List<?> l = (List<?>)o;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  if ( l instanceof LongList ) {
-+   final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
-+   while( s-- != 0 ) if ( i1.nextLong() != i2.nextLong() ) return false;
-+   return true;
-+  }
-+  final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
-+  while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
-+  return true;
-+ }
-+    /** Compares this list to another object. If the
-+     * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
-+     * it throws a <code>ClassCastException</code>.
-+     *
-+     * @param l a list.
-+     * @return if the argument is a {@link java.util.List}, a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     * @throws ClassCastException if the argument is not a list.
-+     */
-+
-+ public int compareTo( final List<? extends Long> l ) {
-+  if ( l == this ) return 0;
-+  if ( l instanceof LongList ) {
-+   final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
-+   int r;
-+   long e1, e2;
-+   while( i1.hasNext() && i2.hasNext() ) {
-+    e1 = i1.nextLong();
-+    e2 = i2.nextLong();
-+    if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
-+   }
-+   return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+  }
-+  ListIterator<? extends Long> i1 = listIterator(), i2 = l.listIterator();
-+  int r;
-+  while( i1.hasNext() && i2.hasNext() ) {
-+   if ( ( r = ((Comparable<? super Long>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
-+  }
-+  return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+ }
-+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
-+	 *
-+	 * @return the hash code for this list.
-+	 */
-+ public int hashCode() {
-+  LongIterator i = iterator();
-+  int h = 1, s = size();
-+  while ( s-- != 0 ) {
-+   long k = i.nextLong();
-+   h = 31 * h + it.unimi.dsi.fastutil.HashCommon.long2int(k);
-+  }
-+  return h;
-+ }
-+ public void push( long o ) {
-+  add( o );
-+ }
-+ public long popLong() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return removeLong( size() - 1 );
-+ }
-+ public long topLong() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return getLong( size() - 1 );
-+ }
-+ public long peekLong( int i ) {
-+  return getLong( size() - 1 - i );
-+ }
-+ public boolean rem( long k ) {
-+  int index = indexOf( k );
-+  if ( index == -1 ) return false;
-+  removeLong( index );
-+  return true;
-+ }
-+ /** Delegates to <code>rem()</code>. */
-+ public boolean remove( final Object o ) {
-+  return rem( ((((Long)(o)).longValue())) );
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final int index, final LongCollection c ) {
-+  return addAll( index, (Collection<? extends Long>)c );
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final int index, final LongList l ) {
-+  return addAll( index, (LongCollection)l );
-+ }
-+ public boolean addAll( final LongCollection c ) {
-+  return addAll( size(), c );
-+ }
-+ public boolean addAll( final LongList l ) {
-+  return addAll( size(), l );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void add( final int index, final Long ok ) {
-+  add( index, ok.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long set( final int index, final Long ok ) {
-+  return (Long.valueOf(set( index, ok.longValue() )));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long get( final int index ) {
-+  return (Long.valueOf(getLong( index )));
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public int indexOf( final Object ok) {
-+  return indexOf( ((((Long)(ok)).longValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public int lastIndexOf( final Object ok ) {
-+  return lastIndexOf( ((((Long)(ok)).longValue())) );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long remove( final int index ) {
-+  return (Long.valueOf(removeLong( index )));
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void push( Long o ) {
-+  push( o.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long pop() {
-+  return Long.valueOf( popLong() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long top() {
-+  return Long.valueOf( topLong() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long peek( int i ) {
-+  return Long.valueOf( peekLong( i ) );
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final LongIterator i = iterator();
-+  int n = size();
-+  long k;
-+  boolean first = true;
-+  s.append("[");
-+  while( n-- != 0 ) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.nextLong();
-+    s.append( String.valueOf( k ) );
-+  }
-+  s.append("]");
-+  return s.toString();
-+ }
-+ public static class LongSubList extends AbstractLongList implements java.io.Serializable {
-+     private static final long serialVersionUID = -7046029254386353129L;
-+  /** The list this sublist restricts. */
-+  protected final LongList l;
-+  /** Initial (inclusive) index of this sublist. */
-+  protected final int from;
-+  /** Final (exclusive) index of this sublist. */
-+  protected int to;
-+  private static final boolean ASSERTS = false;
-+  public LongSubList( final LongList l, final int from, final int to ) {
-+   this.l = l;
-+   this.from = from;
-+   this.to = to;
-+  }
-+  private void assertRange() {
-+   if ( ASSERTS ) {
-+    assert from <= l.size();
-+    assert to <= l.size();
-+    assert to >= from;
-+   }
-+  }
-+  public boolean add( final long k ) {
-+   l.add( to, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+   return true;
-+  }
-+  public void add( final int index, final long k ) {
-+   ensureIndex( index );
-+   l.add( from + index, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public boolean addAll( final int index, final Collection<? extends Long> c ) {
-+   ensureIndex( index );
-+   to += c.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = l.addAll( from + index, c );
-+    assertRange();
-+    return retVal;
-+   }
-+   return l.addAll( from + index, c );
-+  }
-+  public long getLong( int index ) {
-+   ensureRestrictedIndex( index );
-+   return l.getLong( from + index );
-+  }
-+  public long removeLong( int index ) {
-+   ensureRestrictedIndex( index );
-+   to--;
-+   return l.removeLong( from + index );
-+  }
-+  public long set( int index, long k ) {
-+   ensureRestrictedIndex( index );
-+   return l.set( from + index, k );
-+  }
-+  public void clear() {
-+   removeElements( 0, size() );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public int size() {
-+   return to - from;
-+  }
-+  public void getElements( final int from, final long[] a, final int offset, final int length ) {
-+   ensureIndex( from );
-+   if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
-+   l.getElements( this.from + from, a, offset, length );
-+  }
-+  public void removeElements( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   l.removeElements( this.from + from, this.from + to );
-+   this.to -= ( to - from );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public void addElements( int index, final long a[], int offset, int length ) {
-+   ensureIndex( index );
-+   l.addElements( this.from + index, a, offset, length );
-+   this.to += length;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public LongListIterator listIterator( final int index ) {
-+   ensureIndex( index );
-+   return new AbstractLongListIterator () {
-+     int pos = index, last = -1;
-+     public boolean hasNext() { return pos < size(); }
-+     public boolean hasPrevious() { return pos > 0; }
-+     public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getLong( from + ( last = pos++ ) ); }
-+     public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getLong( from + ( last = --pos ) ); }
-+     public int nextIndex() { return pos; }
-+     public int previousIndex() { return pos - 1; }
-+     public void add( long k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      LongSubList.this.add( pos++, k );
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+     public void set( long k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      LongSubList.this.set( last, k );
-+     }
-+     public void remove() {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      LongSubList.this.removeLong( last );
-+      /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+      if ( last < pos ) pos--;
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+    };
-+  }
-+  public LongList subList( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+   return new LongSubList ( this, from, to );
-+  }
-+  public boolean rem( long k ) {
-+   int index = indexOf( k );
-+   if ( index == -1 ) return false;
-+   to--;
-+   l.removeLong( from + index );
-+   if ( ASSERTS ) assertRange();
-+   return true;
-+  }
-+  public boolean remove( final Object o ) {
-+   return rem( ((((Long)(o)).longValue())) );
-+  }
-+  public boolean addAll( final int index, final LongCollection c ) {
-+   ensureIndex( index );
-+   to += c.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = l.addAll( from + index, c );
-+    assertRange();
-+    return retVal;
-+   }
-+   return l.addAll( from + index, c );
-+  }
-+  public boolean addAll( final int index, final LongList l ) {
-+   ensureIndex( index );
-+   to += l.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = this.l.addAll( from + index, l );
-+    assertRange();
-+    return retVal;
-+   }
-+   return this.l.addAll( from + index, l );
-+  }
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
-+ *
-+ * <P>This class provides trivial type-specific implementations of {@link
-+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
-+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
-+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
-+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
-+ * 
-+ *
-+ * @see java.util.ListIterator
-+ */
-+public abstract class AbstractLongListIterator extends AbstractLongBidirectionalIterator implements LongListIterator {
-+ protected AbstractLongListIterator() {}
-+ /** Delegates to the corresponding type-specific method. */
-+ public void set( Long ok ) { set( ok.longValue() ); }
-+ /** Delegates to the corresponding type-specific method. */
-+ public void add( Long ok ) { add( ok.longValue() ); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void set( long k ) { throw new UnsupportedOperationException(); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void add( long k ) { throw new UnsupportedOperationException(); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
-+/**  An abstract class providing basic methods for priority queues implementing a type-specific interface.
-+ *
-+ */
-+public abstract class AbstractLongPriorityQueue extends AbstractPriorityQueue<Long> implements java.io.Serializable, LongPriorityQueue {
-+ private static final long serialVersionUID = 1L;
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public void enqueue( final Long x ) { enqueue( x.longValue() ); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long dequeue() { return (Long.valueOf(dequeueLong())); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long first() { return (Long.valueOf(firstLong())); }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long last() { return (Long.valueOf(lastLong())); }
-+ /** Throws an {@link UnsupportedOperationException}. */
-+ public long lastLong() { throw new UnsupportedOperationException(); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Set;
-+/**  An abstract class providing basic methods for sets implementing a type-specific interface. */
-+public abstract class AbstractLongSet extends AbstractLongCollection implements Cloneable, LongSet {
-+ protected AbstractLongSet() {}
-+ public abstract LongIterator iterator();
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( !( o instanceof Set ) ) return false;
-+  Set<?> s = (Set<?>) o;
-+  if ( s.size() != size() ) return false;
-+  return containsAll(s);
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * The hash code of a set is computed by summing the hash codes of
-+	 * its elements.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0, n = size();
-+  LongIterator i = iterator();
-+  long k;
-+  while( n-- != 0 ) {
-+   k = i.nextLong(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
-+   h += it.unimi.dsi.fastutil.HashCommon.long2int(k);
-+  }
-+  return h;
-+ }
-+ public boolean remove( long k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ /** Delegates to <code>remove()</code>.
-+	 *
-+	 * @param k the element to be removed.
-+	 * @return true if the set was modified.
-+	 */
-+ public boolean rem( long k ) {
-+  return remove( k );
-+ }
-+ /** Delegates to the corresponding type-specific method. */
-+ public boolean remove( final Object o ) {
-+  return remove( ((((Long)(o)).longValue())) );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
-+public abstract class AbstractLongSortedSet extends AbstractLongSet implements LongSortedSet {
-+ protected AbstractLongSortedSet() {}
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public LongSortedSet headSet( final Long to ) {
-+  return headSet( to.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public LongSortedSet tailSet( final Long from ) {
-+  return tailSet( from.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public LongSortedSet subSet( final Long from, final Long to ) {
-+  return subSet( from.longValue(), to.longValue() );
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long first() {
-+  return (Long.valueOf(firstLong()));
-+ }
-+ /** Delegates to the corresponding type-specific method.
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public Long last() {
-+  return (Long.valueOf(lastLong()));
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public LongBidirectionalIterator longIterator() {
-+  return iterator();
-+ }
-+ public abstract LongBidirectionalIterator iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2007-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Map;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectCollections;
-+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
-+import it.unimi.dsi.fastutil.objects.ObjectArrays;
-+/** A simple, brute-force implementation of a map based on two parallel backing arrays. 
-+ * 
-+ * <p>The main purpose of this
-+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very 
-+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
-+ */
-+public class Long2ObjectArrayMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable {
-+ private static final long serialVersionUID = 1L;
-+ /** The keys (valid up to {@link #size}, excluded). */
-+ private transient long[] key;
-+ /** The values (parallel to {@link #key}). */
-+ private transient Object[] value;
-+ /** The number of valid entries in {@link #key} and {@link #value}. */
-+ private int size;
-+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
-+	 * 
-+	 * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
-+	 * 
-+	 * @param key the key array.
-+	 * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
-+	 */
-+ public Long2ObjectArrayMap( final long[] key, final Object[] value ) {
-+  this.key = key;
-+  this.value = value;
-+  size = key.length;
-+  if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
-+ }
-+ /** Creates a new empty array map.
-+	 */
-+ public Long2ObjectArrayMap() {
-+  this.key = LongArrays.EMPTY_ARRAY;
-+  this.value = ObjectArrays.EMPTY_ARRAY;
-+ }
-+ /** Creates a new empty array map of given capacity.
-+	 *
-+	 * @param capacity the initial capacity.
-+	 */
-+ public Long2ObjectArrayMap( final int capacity ) {
-+  this.key = new long[ capacity ];
-+  this.value = new Object[ capacity ];
-+ }
-+ /** Creates a new empty array map copying the entries of a given map.
-+	 *
-+	 * @param m a map.
-+	 */
-+ public Long2ObjectArrayMap( final Long2ObjectMap <V> m ) {
-+  this( m.size() );
-+  putAll( m );
-+ }
-+ /** Creates a new empty array map copying the entries of a given map.
-+	 *
-+	 * @param m a map.
-+	 */
-+ public Long2ObjectArrayMap( final Map<? extends Long, ? extends V> m ) {
-+  this( m.size() );
-+  putAll( m );
-+ }
-+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
-+	 * 
-+	 * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
-+	 * 
-+	 * @param key the key array.
-+	 * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
-+	 * @param size the number of valid elements in <code>key</code> and <code>value</code>.
-+	 */
-+ public Long2ObjectArrayMap( final long[] key, final Object[] value, final int size ) {
-+  this.key = key;
-+  this.value = value;
-+  this.size = size;
-+  if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
-+  if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
-+ }
-+ private final class EntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  @Override
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
-+   return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
-+    int curr = -1, next = 0;
-+    public boolean hasNext() {
-+     return next < size;
-+    }
-+    @SuppressWarnings("unchecked")
-+    public Entry <V> next() {
-+     if ( ! hasNext() ) throw new NoSuchElementException();
-+     return new AbstractLong2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
-+    }
-+    public void remove() {
-+     if ( curr == -1 ) throw new IllegalStateException();
-+     curr = -1;
-+     final int tail = size-- - next--;
-+     System.arraycopy( key, next + 1, key, next, tail );
-+     System.arraycopy( value, next + 1, value, next, tail );
-+     value[ size ] = null;
-+    }
-+   };
-+  }
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
-+   return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
-+    int next = 0, curr = -1;
-+    final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
-+    public boolean hasNext() {
-+     return next < size;
-+    }
-+    @SuppressWarnings("unchecked")
-+    public Entry <V> next() {
-+     if ( ! hasNext() ) throw new NoSuchElementException();
-+     entry.key = key[ curr = next ];
-+     entry.value = (V) value[ next++ ];
-+     return entry;
-+    }
-+    public void remove() {
-+     if ( curr == -1 ) throw new IllegalStateException();
-+     curr = -1;
-+     final int tail = size-- - next--;
-+     System.arraycopy( key, next + 1, key, next, tail );
-+     System.arraycopy( value, next + 1, value, next, tail );
-+     value[ size ] = null;
-+    }
-+   };
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( Object o ) {
-+   if ( ! ( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   return Long2ObjectArrayMap.this.containsKey( k ) && ( (Long2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Long2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
-+  }
-+  @SuppressWarnings("unchecked")
-+  @Override
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   final V v = (e.getValue());
-+   final int oldPos = Long2ObjectArrayMap.this.findKey( k );
-+   if ( oldPos == -1 || ! ( (v) == null ? (Long2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Long2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
-+   final int tail = size - oldPos - 1;
-+   System.arraycopy( Long2ObjectArrayMap.this.key, oldPos + 1, Long2ObjectArrayMap.this.key, oldPos, tail );
-+   System.arraycopy( Long2ObjectArrayMap.this.value, oldPos + 1, Long2ObjectArrayMap.this.value, oldPos, tail );
-+   Long2ObjectArrayMap.this.size--;
-+   Long2ObjectArrayMap.this.value[ size ] = null;
-+   return true;
-+  }
-+ }
-+ public FastEntrySet <V> long2ObjectEntrySet() {
-+  return new EntrySet();
-+ }
-+ private int findKey( final long k ) {
-+  final long[] key = this.key;
-+  for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
-+  return -1;
-+ }
-+ @SuppressWarnings("unchecked")
-+ public V get( final long k ) {
-+  final long[] key = this.key;
-+  for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
-+  return defRetValue;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ @Override
-+ public void clear() {
-+  for( int i = size; i-- != 0; ) {
-+   value[ i ] = null;
-+  }
-+  size = 0;
-+ }
-+ @Override
-+ public boolean containsKey( final long k ) {
-+  return findKey( k ) != -1;
-+ }
-+ @Override
-+ public boolean containsValue( Object v ) {
-+  for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ @Override
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ @Override
-+ @SuppressWarnings("unchecked")
-+ public V put( long k, V v ) {
-+  final int oldKey = findKey( k );
-+  if ( oldKey != -1 ) {
-+   final V oldValue = (V) value[ oldKey ];
-+   value[ oldKey ] = v;
-+   return oldValue;
-+  }
-+  if ( size == key.length ) {
-+   final long[] newKey = new long[ size == 0 ? 2 : size * 2 ];
-+   final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
-+   for( int i = size; i-- != 0; ) {
-+    newKey[ i ] = key[ i ];
-+    newValue[ i ] = value[ i ];
-+   }
-+   key = newKey;
-+   value = newValue;
-+  }
-+  key[ size ] = k;
-+  value[ size ] = v;
-+  size++;
-+  return defRetValue;
-+ }
-+ @Override
-+ @SuppressWarnings("unchecked")
-+ public V remove( final long k ) {
-+  final int oldPos = findKey( k );
-+  if ( oldPos == -1 ) return defRetValue;
-+  final V oldValue = (V) value[ oldPos ];
-+  final int tail = size - oldPos - 1;
-+  System.arraycopy( key, oldPos + 1, key, oldPos, tail );
-+  System.arraycopy( value, oldPos + 1, value, oldPos, tail );
-+  size--;
-+  value[ size ] = null;
-+  return oldValue;
-+ }
-+ @Override
-+ public LongSet keySet() {
-+  return new LongArraySet ( key, size );
-+ }
-+ @Override
-+ public ObjectCollection <V> values() {
-+  return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectArrayMap <V> clone() {
-+  Long2ObjectArrayMap <V> c;
-+  try {
-+   c = (Long2ObjectArrayMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) {
-+   s.writeLong( key[ i ] );
-+   s.writeObject( value[ i ] );
-+  }
-+ }
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  key = new long[ size ];
-+  value = new Object[ size ];
-+  for( int i = 0; i < size; i++ ) {
-+   key[ i ] = s.readLong();
-+   value[ i ] = s.readObject();
-+  }
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Function;
-+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
-+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
-+ * a key.  Rather, they return a {@linkplain #defaultReturnValue() default
-+ * return value}, which is set to 0 cast to the return type (<code>false</code>
-+ * for booleans) at creation, but can be changed using the
-+ * <code>defaultReturnValue()</code> method. 
-+ *
-+ * <P>For uniformity reasons, even maps returning objects implement the default
-+ * return value (of course, in this case the default return value is
-+ * initialized to <code>null</code>).
-+ *
-+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
-+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
-+ * that standard versions of <code>get()</code>, <code>put()</code> and
-+ * <code>remove()</code> for maps with primitive-type values <em>return
-+ * <code>null</code> to denote missing keys</em> rather than wrap the default
-+ * return value in an object (of course, for maps with object keys and values
-+ * this is not possible, as there is no type-specific version).
-+ *
-+ * @see Function
-+ */
-+public interface Long2ObjectFunction <V> extends Function<Long, V> {
-+ /** Adds a pair to the map.
-+	 *
-+	 * @param key the key.
-+	 * @param value the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#put(Object,Object)
-+	 */
-+ V put( long key, V value );
-+ /** Returns the value to which the given key is mapped.
-+	 *
-+	 * @param key the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#get(Object)
-+	 */
-+ V get( long key );
-+ /** Removes the mapping with the given key.
-+	 * @param key the key.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 * @see Function#remove(Object)
-+	 */
-+ V remove( long key );
-+ /**
-+	 * @see Function#containsKey(Object)
-+	 */
-+ boolean containsKey( long key );
-+ /** Sets the default return value. 
-+	 *
-+	 * This value must be returned by type-specific versions of
-+	 * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
-+	 * denote that the map does not contain the specified key. It must be
-+	 * 0/<code>false</code>/<code>null</code> by default.
-+	 *
-+	 * @param rv the new default return value.
-+	 * @see #defaultReturnValue()
-+	 */
-+ void defaultReturnValue( V rv );
-+ /** Gets the default return value.
-+	 *
-+	 * @return the current default return value.
-+	 */
-+ V defaultReturnValue();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** A class providing static methods and objects that do useful things with type-specific functions.
-+ *
-+ * @see it.unimi.dsi.fastutil.Function
-+ * @see java.util.Collections
-+ */
-+public class Long2ObjectFunctions {
-+ private Long2ObjectFunctions() {}
-+ /** An immutable class representing an empty type-specific function.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific function.
-+	 */
-+ public static class EmptyFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyFunction() {}
-+  public V get( final long k ) { return (null); }
-+  public boolean containsKey( final long k ) { return false; }
-+  public V defaultReturnValue() { return (null); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final Object k ) { return null; }
-+  public int size() { return 0; }
-+  public void clear() {}
-+  private Object readResolve() { return EMPTY_FUNCTION; }
-+  public Object clone() { return EMPTY_FUNCTION; }
-+ }
-+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
-+ /** An immutable class representing a type-specific singleton function.	 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific function.
-+	 */
-+ public static class Singleton <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final long key;
-+  protected final V value;
-+  protected Singleton( final long key, final V value ) {
-+   this.key = key;
-+   this.value = value;
-+  }
-+  public boolean containsKey( final long k ) { return ( (key) == (k) ); }
-+  public V get( final long k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
-+  public int size() { return 1; }
-+  public Object clone() { return this; }
-+ }
-+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned function is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned function.
-+	 * @param value the only value of the returned function.
-+	 * @return a type-specific immutable function containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectFunction <V> singleton( final long key, V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned function is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned function.
-+	 * @param value the only value of the returned function.
-+	 * @return a type-specific immutable function containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectFunction <V> singleton( final Long key, final V value ) {
-+  return new Singleton <V>( ((key).longValue()), (value) );
-+ }
-+ /** A synchronized wrapper class for functions. */
-+ public static class SynchronizedFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectFunction <V> function;
-+  protected final Object sync;
-+  protected SynchronizedFunction( final Long2ObjectFunction <V> f, final Object sync ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedFunction( final Long2ObjectFunction <V> f ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+   this.sync = this;
-+  }
-+  public int size() { synchronized( sync ) { return function.size(); } }
-+  public boolean containsKey( final long k ) { synchronized( sync ) { return function.containsKey( k ); } }
-+  public V defaultReturnValue() { synchronized( sync ) { return function.defaultReturnValue(); } }
-+  public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { function.defaultReturnValue( defRetValue ); } }
-+  public V put( final long k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
-+  public void clear() { synchronized( sync ) { function.clear(); } }
-+  public String toString() { synchronized( sync ) { return function.toString(); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V put( final Long k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
-+  @Override
-+  public V get( final Object k ) { synchronized( sync ) { return function.get( k ); } }
-+  @Override
-+  public V remove( final Object k ) { synchronized( sync ) { return function.remove( k ); } }
-+  @Override
-+  public V remove( final long k ) { synchronized( sync ) { return function.remove( k ); } }
-+  @Override
-+  public V get( final long k ) { synchronized( sync ) { return function.get( k ); } }
-+  public boolean containsKey( final Object ok ) { synchronized( sync ) { return function.containsKey( ok ); } }
-+ }
-+ /** Returns a synchronized type-specific function backed by the given type-specific function.
-+	 *
-+	 * @param f the function to be wrapped in a synchronized function.
-+	 * @return a synchronized view of the specified function.
-+	 * @see java.util.Collections#synchronizedMap(java.util.Map)
-+	 */
-+ public static <V> Long2ObjectFunction <V> synchronize( final Long2ObjectFunction <V> f ) { return new SynchronizedFunction <V>( f ); }
-+ /** Returns a synchronized type-specific function backed by the given type-specific function, using an assigned object to synchronize.
-+	 *
-+	 * @param f the function to be wrapped in a synchronized function.
-+	 * @param sync an object that will be used to synchronize the access to the function.
-+	 * @return a synchronized view of the specified function.
-+	 * @see java.util.Collections#synchronizedMap(java.util.Map)
-+	 */
-+ public static <V> Long2ObjectFunction <V> synchronize( final Long2ObjectFunction <V> f, final Object sync ) { return new SynchronizedFunction <V>( f, sync ); }
-+ /** An unmodifiable wrapper class for functions. */
-+ public static class UnmodifiableFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectFunction <V> function;
-+  protected UnmodifiableFunction( final Long2ObjectFunction <V> f ) {
-+   if ( f == null ) throw new NullPointerException();
-+   this.function = f;
-+  }
-+  public int size() { return function.size(); }
-+  public boolean containsKey( final long k ) { return function.containsKey( k ); }
-+  public V defaultReturnValue() { return function.defaultReturnValue(); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  public V put( final long k, final V v ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return function.toString(); }
-+  @Override
-+  public V remove( final long k ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final long k ) { return function.get( k ); }
-+  public boolean containsKey( final Object ok ) { return function.containsKey( ok ); }
-+  @Override
-+  public V remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  @Override
-+  public V get( final Object k ) { return function.get( k ); }
-+ }
-+ /** Returns an unmodifiable type-specific function backed by the given type-specific function.
-+	 *
-+	 * @param f the function to be wrapped in an unmodifiable function.
-+	 * @return an unmodifiable view of the specified function.
-+	 * @see java.util.Collections#unmodifiableMap(java.util.Map)
-+	 */
-+ public static <V> Long2ObjectFunction <V> unmodifiable( final Long2ObjectFunction <V> f ) { return new UnmodifiableFunction <V>( f ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Comparator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+/**  A type-specific linked hash map with with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
-+ * have been added to the map (addition of pairs whose key is already present 
-+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
-+ * order of the keys. The order is kept by means of a doubly linked list, represented
-+ * <i>via</i> an array of longs parallel to the table.
-+ *
-+ * <P>This class implements the interface of a sorted map, so to allow easy
-+ * access of the iteration order: for instance, you can get the first key
-+ * in iteration order with {@code firstKey()} without having to create an
-+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
-+ * contract because all submap methods throw an exception and {@link
-+ * #comparator()} returns always <code>null</code>.
-+ *
-+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
-+ * to use instances of this class as a cache (e.g., with LRU policy).
-+ *
-+ * <P>The iterators provided by the views of this class using are type-specific
-+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
-+ * element <em>which is a key of the map</em>, or
-+ * a {@link NoSuchElementException} exception will be thrown.
-+ * If, however, the provided element is not the first or last key in the
-+ * set, the first access to the list index will require linear time, as in the worst case
-+ * the entire key set must be scanned in iteration order to retrieve the positional
-+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
-+ * however, all operations will be performed in constant time.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Long2ObjectLinkedOpenHashMap <V> extends AbstractLong2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient long[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int first = -1;
-+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
-+ protected transient int last = -1;
-+ /** For each entry, the next and the previous entry in iteration order,
-+     * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
-+     * The first entry contains predecessor -1, and the last entry 
-+     * contains successor -1. */
-+     protected transient long[] link;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastSortedEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient LongSortedSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectLinkedOpenHashMap( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new long[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+  link = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v, final float f ) {
-+  this( k.length, f );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  fixPointers( pos );
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  fixPointers( n );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Long,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final long k, final V v) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final long k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Long ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).longValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  long curr;
-+  final long[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+   fixPointers( pos, last );
-+  }
-+ }
-+
-+ public V remove( final long k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final long k = ((((Long)(ok)).longValue()));
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ private V setValue( final int pos, final V v ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** Removes the mapping associated with the first key in iteration order.
-+	 * @return the value previously associated with the first key in iteration order.
-+	 * @throws NoSuchElementException is this map is empty.
-+	 */
-+ public V removeFirst() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = first;
-+  // Abbreviated version of fixPointers(pos)
-+  first = (int) link[ pos ];
-+  if ( 0 <= first ) {
-+   // Special case of SET_PREV( link[ first ], -1 )
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  size--;
-+  final V v = value[ pos ];
-+  if ( pos == n ) {
-+   containsNullKey = false;
-+   value[ n ] = null;
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return v;
-+ }
-+ /** Removes the mapping associated with the last key in iteration order.
-+	 * @return the value previously associated with the last key in iteration order.
-+	 * @throws NoSuchElementException is this map is empty.
-+	 */
-+ public V removeLast() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  final int pos = last;
-+  // Abbreviated version of fixPointers(pos)
-+  last = (int) ( link[ pos ] >>> 32 );
-+  if ( 0 <= last ) {
-+   // Special case of SET_NEXT( link[ last ], -1 )
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  size--;
-+  final V v = value[ pos ];
-+  if ( pos == n ) {
-+   containsNullKey = false;
-+   value[ n ] = null;
-+  }
-+  else shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return v;
-+ }
-+ private void moveIndexToFirst( final int i ) {
-+  if ( size == 1 || first == i ) return;
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   // Special case of SET_NEXT( link[ last ], -1 );
-+   link[ last ] |= -1 & 0xFFFFFFFFL;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+  first = i;
-+ }
-+ private void moveIndexToLast( final int i ) {
-+  if ( size == 1 || last == i ) return;
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   // Special case of SET_PREV( link[ first ], -1 );
-+   link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+  }
-+  else {
-+   final long linki = link[ i ];
-+   final int prev = (int) ( linki >>> 32 );
-+   final int next = (int) linki;
-+   link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+  }
-+  link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+  last = i;
-+ }
-+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V getAndMoveToFirst( final long k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToFirst( n );
-+    return value[ n ];
-+   }
-+   return defRetValue;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) {
-+   moveIndexToFirst( pos );
-+   return value[ pos ];
-+  }
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) {
-+    moveIndexToFirst( pos );
-+    return value[ pos ];
-+   }
-+  }
-+ }
-+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V getAndMoveToLast( final long k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToLast( n );
-+    return value[ n ];
-+   }
-+   return defRetValue;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) {
-+   moveIndexToLast( pos );
-+   return value[ pos ];
-+  }
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) {
-+    moveIndexToLast( pos );
-+    return value[ pos ];
-+   }
-+  }
-+ }
-+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @param v the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V putAndMoveToFirst( final long k, final V v ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToFirst( n );
-+    return setValue( n, v );
-+   }
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) {
-+     moveIndexToFirst( pos );
-+     return setValue( pos, v );
-+    }
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) {
-+      moveIndexToFirst( pos );
-+      return setValue( pos, v );
-+     }
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
-+   first = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return defRetValue;
-+ }
-+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
-+	 *
-+	 * @param k the key.
-+	 * @param v the value.
-+	 * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
-+	 */
-+ public V putAndMoveToLast( final long k, final V v ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) {
-+    moveIndexToLast( n );
-+    return setValue( n, v );
-+   }
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) {
-+     moveIndexToLast( pos );
-+     return setValue( pos, v );
-+    }
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) {
-+      moveIndexToLast( pos );
-+      return setValue( pos, v );
-+     }
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size == 0 ) {
-+   first = last = pos;
-+   // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
-+   link[ pos ] = -1L;
-+  }
-+  else {
-+   link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
-+   last = pos;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return defRetValue;
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Long ok ) {
-+  if ( ok == null ) return null;
-+  final long k = ((ok).longValue());
-+  if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final long k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final long k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final long key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+  first = last = -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long getKey() {
-+   return (Long.valueOf(key[ index ]));
-+  }
-+  public long getLongKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** Modifies the {@link #link} vector so that the given entry is removed.
-+	 * This method will complete in constant time.
-+	 *
-+	 * @param i the index of an entry. 
-+	 */
-+ protected void fixPointers( final int i ) {
-+  if ( size == 0 ) {
-+   first = last = -1;
-+   return;
-+  }
-+  if ( first == i ) {
-+   first = (int) link[ i ];
-+   if (0 <= first) {
-+    // Special case of SET_PREV( link[ first ], -1 )
-+    link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
-+   }
-+   return;
-+  }
-+  if ( last == i ) {
-+   last = (int) ( link[ i ] >>> 32 );
-+   if (0 <= last) {
-+    // Special case of SET_NEXT( link[ last ], -1 )
-+    link[ last ] |= -1 & 0xFFFFFFFFL;
-+   }
-+   return;
-+  }
-+  final long linki = link[ i ];
-+  final int prev = (int) ( linki >>> 32 );
-+  final int next = (int) linki;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
-+ }
-+ /** Modifies the {@link #link} vector for a shift from s to d.
-+	 * <P>This method will complete in constant time.
-+	 *
-+	 * @param s the source position.
-+	 * @param d the destination position.
-+	 */
-+ protected void fixPointers( int s, int d ) {
-+  if ( size == 1 ) {
-+   first = last = d;
-+   // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
-+   link[ d ] = -1L;
-+   return;
-+  }
-+  if ( first == s ) {
-+   first = d;
-+   link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  if ( last == s ) {
-+   last = d;
-+   link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   link[ d ] = link[ s ];
-+   return;
-+  }
-+  final long links = link[ s ];
-+  final int prev = (int) ( links >>> 32 );
-+  final int next = (int) links;
-+  link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+  link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+  link[ d ] = links;
-+ }
-+ /** Returns the first key of this map in iteration order.
-+	 *
-+	 * @return the first key in iteration order.
-+	 */
-+ public long firstLongKey() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ first ];
-+ }
-+ /** Returns the last key of this map in iteration order.
-+	 *
-+	 * @return the last key in iteration order.
-+	 */
-+ public long lastLongKey() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+  return key[ last ];
-+ }
-+ public LongComparator comparator() { return null; }
-+ public Long2ObjectSortedMap <V> tailMap( long from ) { throw new UnsupportedOperationException(); }
-+ public Long2ObjectSortedMap <V> headMap( long to ) { throw new UnsupportedOperationException(); }
-+ public Long2ObjectSortedMap <V> subMap( long from, long to ) { throw new UnsupportedOperationException(); }
-+ /** A list iterator over a linked map.
-+	 *
-+	 * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
-+	 */
-+ private class MapIterator {
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
-+  int prev = -1;
-+  /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
-+  int next = -1;
-+  /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
-+  int curr = -1;
-+  /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
-+  int index = -1;
-+  private MapIterator() {
-+   next = first;
-+   index = 0;
-+  }
-+  private MapIterator( final long from ) {
-+   if ( ( (from) == (0) ) ) {
-+    if ( Long2ObjectLinkedOpenHashMap.this.containsNullKey ) {
-+     next = (int) link[ n ];
-+     prev = n;
-+     return;
-+    }
-+    else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
-+   }
-+   if ( ( (key[ last ]) == (from) ) ) {
-+    prev = last;
-+    index = size;
-+    return;
-+   }
-+   // The starting point.
-+   int pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (from) ) & mask;
-+   // There's always an unused entry.
-+   while( ! ( (key[ pos ]) == (0) ) ) {
-+    if ( ( (key[ pos ]) == (from) ) ) {
-+     // Note: no valid index known.
-+     next = (int) link[ pos ];
-+     prev = pos;
-+     return;
-+    }
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
-+  }
-+  public boolean hasNext() { return next != -1; }
-+  public boolean hasPrevious() { return prev != -1; }
-+  private final void ensureIndexKnown() {
-+   if ( index >= 0 ) return;
-+   if ( prev == -1 ) {
-+    index = 0;
-+    return;
-+   }
-+   if ( next == -1 ) {
-+    index = size;
-+    return;
-+   }
-+   int pos = first;
-+   index = 1;
-+   while( pos != prev ) {
-+    pos = (int) link[ pos ];
-+    index++;
-+   }
-+  }
-+  public int nextIndex() {
-+   ensureIndexKnown();
-+   return index;
-+  }
-+  public int previousIndex() {
-+   ensureIndexKnown();
-+   return index - 1;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = next;
-+   next = (int) link[ curr ];
-+   prev = curr;
-+   if ( index >= 0 ) index++;
-+   return curr;
-+  }
-+  public int previousEntry() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = prev;
-+   prev = (int) ( link[ curr ] >>> 32 );
-+   next = curr;
-+   if ( index >= 0 ) index--;
-+   return curr;
-+  }
-+  public void remove() {
-+   ensureIndexKnown();
-+   if ( curr == -1 ) throw new IllegalStateException();
-+   if ( curr == prev ) {
-+    /* If the last operation was a next(), we are removing an entry that preceeds
-+				   the current index, and thus we must decrement it. */
-+    index--;
-+    prev = (int) ( link[ curr ] >>> 32 );
-+   }
-+   else
-+    next = (int) link[ curr ];
-+   size--;
-+   /* Now we manually fix the pointers. Because of our knowledge of next
-+			   and prev, this is going to be faster than calling fixPointers(). */
-+   if ( prev == -1 ) first = next;
-+   else
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+   if ( next == -1 ) last = prev;
-+   else
-+    link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+   int last, slot, pos = curr;
-+   curr = -1;
-+   if ( pos == n ) {
-+    Long2ObjectLinkedOpenHashMap.this.containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else {
-+    long curr;
-+    final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
-+    // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.			
-+    for(;;) {
-+     pos = ( ( last = pos ) + 1 ) & mask;
-+     for(;;) {
-+      if ( ( (curr = key[ pos ]) == (0) ) ) {
-+       key[ last ] = (0);
-+       value[ last ] = null;
-+       return;
-+      }
-+      slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+      if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+      pos = ( pos + 1 ) & mask;
-+     }
-+     key[ last ] = curr;
-+     value[ last ] = value[ pos ];
-+     if ( next == pos ) next = last;
-+     if ( prev == pos ) prev = last;
-+     fixPointers( pos, last );
-+    }
-+   }
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+  public int back( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasPrevious() ) previousEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public EntryIterator() {}
-+  public EntryIterator( long from ) {
-+   super( from );
-+  }
-+  public MapEntry next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  public MapEntry previous() {
-+   return entry = new MapEntry( previousEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+  public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
-+  final MapEntry entry = new MapEntry();
-+  public FastEntryIterator() {}
-+  public FastEntryIterator( long from ) {
-+   super( from );
-+  }
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+  public MapEntry previous() {
-+   entry.index = previousEntry();
-+   return entry;
-+  }
-+  public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSortedSet<Long2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
-+  public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public Comparator<? super Long2ObjectMap.Entry <V> > comparator() { return null; }
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > subSet( Long2ObjectMap.Entry <V> fromElement, Long2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > headSet( Long2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > tailSet( Long2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
-+  public Long2ObjectMap.Entry <V> first() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return new MapEntry( Long2ObjectLinkedOpenHashMap.this.first );
-+  }
-+  public Long2ObjectMap.Entry <V> last() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return new MapEntry( Long2ObjectLinkedOpenHashMap.this.last );
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   if ( ( (k) == (0) ) ) return ( Long2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   long curr;
-+   final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   final V v = (e.getValue());
-+   if ( ( (k) == (0) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   long curr;
-+   final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (curr) == (k) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (curr) == (k) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Long2ObjectLinkedOpenHashMap.this.clear();
-+  }
-+  public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator( final Long2ObjectMap.Entry <V> from ) {
-+   return new EntryIterator( from.getLongKey() );
-+  }
-+  public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( final Long2ObjectMap.Entry <V> from ) {
-+   return new FastEntryIterator( from.getLongKey() );
-+  }
-+ }
-+ public FastSortedEntrySet <V> long2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements LongListIterator {
-+  public KeyIterator( final long k ) { super( k ); }
-+  public long previousLong() { return key[ previousEntry() ]; }
-+  public void set( long k ) { throw new UnsupportedOperationException(); }
-+  public void add( long k ) { throw new UnsupportedOperationException(); }
-+  public Long previous() { return (Long.valueOf(key[ previousEntry() ])); }
-+  public void set( Long ok ) { throw new UnsupportedOperationException(); }
-+  public void add( Long ok ) { throw new UnsupportedOperationException(); }
-+  public KeyIterator() { super(); }
-+  public long nextLong() { return key[ nextEntry() ]; }
-+  public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractLongSortedSet {
-+  public LongListIterator iterator( final long from ) {
-+   return new KeyIterator( from );
-+  }
-+  public LongListIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( long k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( long k ) {
-+   final int oldSize = size;
-+   Long2ObjectLinkedOpenHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Long2ObjectLinkedOpenHashMap.this.clear();
-+  }
-+  public long firstLong() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return key[ first ];
-+  }
-+  public long lastLong() {
-+   if ( size == 0 ) throw new NoSuchElementException();
-+   return key[ last ];
-+  }
-+  public LongComparator comparator() { return null; }
-+  final public LongSortedSet tailSet( long from ) { throw new UnsupportedOperationException(); }
-+  final public LongSortedSet headSet( long to ) { throw new UnsupportedOperationException(); }
-+  final public LongSortedSet subSet( long from, long to ) { throw new UnsupportedOperationException(); }
-+ }
-+ public LongSortedSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
-+  public V previous() { return value[ previousEntry() ]; }
-+  public void set( V v ) { throw new UnsupportedOperationException(); }
-+  public void add( V v ) { throw new UnsupportedOperationException(); }
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Long2ObjectLinkedOpenHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final long newKey[] = new long[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = first, prev = -1, newPrev = -1, t, pos;
-+  final long link[] = this.link;
-+  final long newLink[] = new long[ newN + 1 ];
-+  first = -1;
-+  for( int j = size; j-- != 0; ) {
-+   if ( ( (key[ i ]) == (0) ) ) pos = newN;
-+   else {
-+    pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask;
-+    while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+   if ( prev != -1 ) {
-+    newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    newPrev = pos;
-+   }
-+   else {
-+    newPrev = first = pos;
-+    // Special case of SET(newLink[ pos ], -1, -1);
-+    newLink[ pos ] = -1L;
-+   }
-+   t = i;
-+   i = (int) link[ i ];
-+   prev = t;
-+  }
-+  this.link = newLink;
-+  this.last = newPrev;
-+  if ( newPrev != -1 )
-+   // Special case of SET_NEXT( newLink[ newPrev ], -1 );
-+   newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectLinkedOpenHashMap <V> clone() {
-+  Long2ObjectLinkedOpenHashMap <V> c;
-+  try {
-+   c = (Long2ObjectLinkedOpenHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  c.link = link.clone();
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeLong( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final long key[] = this.key = new long[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  final long link[] = this.link = new long[ n + 1 ];
-+  int prev = -1;
-+  first = last = -1;
-+  long k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readLong();
-+   v = (V) s.readObject();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+   if ( first != -1 ) {
-+    link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
-+    link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
-+    prev = pos;
-+   }
-+   else {
-+    prev = first = pos;
-+    // Special case of SET_PREV( newLink[ pos ], -1 );
-+    link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
-+   }
-+  }
-+  last = prev;
-+  if ( prev != -1 )
-+   // Special case of SET_NEXT( link[ prev ], -1 );
-+   link[ prev ] |= -1 & 0xFFFFFFFFL;
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import java.util.Map;
-+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
-+ *
-+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
-+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
-+ *
-+ * <P>A submap or subset may or may not have an
-+ * independent default return value (which however must be initialized to the
-+ * default return value of the originator).
-+ *
-+ * @see Map
-+ */
-+public interface Long2ObjectMap <V> extends Long2ObjectFunction <V>, Map<Long,V> {
-+ /** An entry set providing fast iteration. 
-+	 *
-+	 * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
-+	 * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
-+	 * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
-+	 * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
-+	 * by returning always the same entry</em> (of course, mutated).
-+	 */
-+ public interface FastEntrySet <V> extends ObjectSet<Long2ObjectMap.Entry <V> > {
-+  /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
-+		 *
-+		 * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
-+		 */
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator();
-+ }
-+ /** Returns a set view of the mappings contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
-+	 *
-+	 * @return a set view of the mappings contained in this map.
-+	 * @see Map#entrySet()
-+	 */
-+ ObjectSet<Map.Entry<Long, V>> entrySet();
-+ /** Returns a type-specific set view of the mappings contained in this map.
-+	 *
-+	 * <p>This method is necessary because there is no inheritance along
-+	 * type parameters: it is thus impossible to strengthen {@link #entrySet()}
-+	 * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
-+	 * of type-specific entries (the latter makes it possible to
-+	 * access keys and values with type-specific methods).
-+	 *
-+	 * @return a type-specific set view of the mappings contained in this map.
-+	 * @see #entrySet()
-+	 */
-+ ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
-+ /** Returns a set view of the keys contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
-+	 *
-+	 * @return a set view of the keys contained in this map.
-+	 * @see Map#keySet()
-+	 */
-+ LongSet keySet();
-+ /** Returns a set view of the values contained in this map.
-+	 *  <P>Note that this specification strengthens the one given in {@link Map#values()}.
-+	 *
-+	 * @return a set view of the values contained in this map.
-+	 * @see Map#values()
-+	 */
-+ ObjectCollection <V> values();
-+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
-+	 *  that use polymorphism to avoid (un)boxing.
-+	 *
-+	 * @see java.util.Map.Entry
-+	 */
-+ interface Entry <V> extends Map.Entry <Long,V> {
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  Long getKey();
-+  /**
-+		 * @see java.util.Map.Entry#getKey()
-+		 */
-+  long getLongKey();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectSet;
-+import it.unimi.dsi.fastutil.objects.ObjectSets;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectCollections;
-+import java.util.Map;
-+/** A class providing static methods and objects that do useful things with type-specific maps.
-+ *
-+ * @see it.unimi.dsi.fastutil.Maps
-+ * @see java.util.Collections
-+ */
-+public class Long2ObjectMaps {
-+ private Long2ObjectMaps() {}
-+ /** An immutable class representing an empty type-specific map.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific map.
-+	 */
-+ public static class EmptyMap <V> extends Long2ObjectFunctions.EmptyFunction <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyMap() {}
-+  public boolean containsValue( final Object v ) { return false; }
-+  public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
-+ 
-+  public LongSet keySet() { return LongSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
-+        private Object readResolve() { return EMPTY_MAP; }
-+  public Object clone() { return EMPTY_MAP; }
-+  public boolean isEmpty() { return true; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
-+  public int hashCode() { return 0; }
-+  public boolean equals( final Object o ) {
-+   if ( ! ( o instanceof Map ) ) return false;
-+   return ((Map<?,?>)o).isEmpty();
-+  }
-+  public String toString() { return "{}"; }
-+ }
-+ /** An empty type-specific map (immutable). It is serializable and cloneable. 
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
-+ /** Return an empty map (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
-+	 * @return an empty map (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <V> Long2ObjectMap <V> emptyMap() {
-+  return EMPTY_MAP;
-+ }
-+ /** An immutable class representing a type-specific singleton map.	 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific map.
-+	 */
-+ public static class Singleton <V> extends Long2ObjectFunctions.Singleton <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
-+  protected transient LongSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected Singleton( final long key, final V value ) {
-+   super( key, value );
-+  }
-+  public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
-+  public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
-+  public LongSet keySet() { if ( keys == null ) keys = LongSets.singleton( key ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
-+  protected class SingletonEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long,V> {
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+   public Long getKey() { return (Long.valueOf(Singleton.this.key)); }
-+   public V getValue() { return (Singleton.this.value); }
-+   public long getLongKey() { return Singleton.this.key; }
-+   public V setValue( final V value ) { throw new UnsupportedOperationException(); }
-+   public boolean equals( final Object o ) {
-+    if (!(o instanceof Map.Entry)) return false;
-+    Map.Entry<?,?> e = (Map.Entry<?,?>)o;
-+    return ( (Singleton.this.key) == (((((Long)(e.getKey())).longValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
-+   }
-+   public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
-+   public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
-+  }
-+  public boolean isEmpty() { return false; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
-+  public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
-+  public boolean equals( final Object o ) {
-+   if ( o == this ) return true;
-+   if ( ! ( o instanceof Map ) ) return false;
-+   Map<?,?> m = (Map<?,?>)o;
-+   if ( m.size() != 1 ) return false;
-+   return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
-+  }
-+  public String toString() { return "{" + key + "=>" + value + "}"; }
-+ }
-+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned map.
-+	 * @param value the only value of the returned map.
-+	 * @return a type-specific immutable map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectMap <V> singleton( final long key, V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned map.
-+	 * @param value the only value of the returned map.
-+	 * @return a type-specific immutable map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectMap <V> singleton( final Long key, final V value ) {
-+  return new Singleton <V>( ((key).longValue()), (value) );
-+ }
-+ /** A synchronized wrapper class for maps. */
-+ public static class SynchronizedMap <V> extends Long2ObjectFunctions.SynchronizedFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectMap <V> map;
-+  protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
-+  protected transient LongSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected SynchronizedMap( final Long2ObjectMap <V> m, final Object sync ) {
-+   super( m, sync );
-+   this.map = m;
-+  }
-+  protected SynchronizedMap( final Long2ObjectMap <V> m ) {
-+   super( m );
-+   this.map = m;
-+  }
-+  public int size() { synchronized( sync ) { return map.size(); } }
-+  public boolean containsKey( final long k ) { synchronized( sync ) { return map.containsKey( k ); } }
-+  public boolean containsValue( final Object v ) { synchronized( sync ) { return map.containsValue( v ); } }
-+  public V defaultReturnValue() { synchronized( sync ) { return map.defaultReturnValue(); } }
-+  public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { map.defaultReturnValue( defRetValue ); } }
-+  public V put( final long k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
-+  //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { synchronized( sync ) { map.putAll( c ); } }
-+  public void putAll( final Map<? extends Long, ? extends V> m ) { synchronized( sync ) { map.putAll( m ); } }
-+  public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.synchronize( map.long2ObjectEntrySet(), sync ); return entries; }
-+  public LongSet keySet() { if ( keys == null ) keys = LongSets.synchronize( map.keySet(), sync ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.synchronize( map.values(), sync ); return values; }
-+  public void clear() { synchronized( sync ) { map.clear(); } }
-+  public String toString() { synchronized( sync ) { return map.toString(); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V put( final Long k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final long k ) { synchronized( sync ) { return map.remove( k ); } }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final long k ) { synchronized( sync ) { return map.get( k ); } }
-+  public boolean containsKey( final Object ok ) { synchronized( sync ) { return map.containsKey( ok ); } }
-+  public boolean isEmpty() { synchronized( sync ) { return map.isEmpty(); } }
-+  public ObjectSet<Map.Entry<Long, V>> entrySet() { synchronized( sync ) { return map.entrySet(); } }
-+  public int hashCode() { synchronized( sync ) { return map.hashCode(); } }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return map.equals( o ); } }
-+ }
-+ /** Returns a synchronized type-specific map backed by the given type-specific map.
-+	 *
-+	 * @param m the map to be wrapped in a synchronized map.
-+	 * @return a synchronized view of the specified map.
-+	 * @see java.util.Collections#synchronizedMap(Map)
-+	 */
-+ public static <V> Long2ObjectMap <V> synchronize( final Long2ObjectMap <V> m ) { return new SynchronizedMap <V>( m ); }
-+ /** Returns a synchronized type-specific map backed by the given type-specific map, using an assigned object to synchronize.
-+	 *
-+	 * @param m the map to be wrapped in a synchronized map.
-+	 * @param sync an object that will be used to synchronize the access to the map.
-+	 * @return a synchronized view of the specified map.
-+	 * @see java.util.Collections#synchronizedMap(Map)
-+	 */
-+ public static <V> Long2ObjectMap <V> synchronize( final Long2ObjectMap <V> m, final Object sync ) { return new SynchronizedMap <V>( m, sync ); }
-+ /** An unmodifiable wrapper class for maps. */
-+ public static class UnmodifiableMap <V> extends Long2ObjectFunctions.UnmodifiableFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectMap <V> map;
-+  protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
-+  protected transient LongSet keys;
-+  protected transient ObjectCollection <V> values;
-+  protected UnmodifiableMap( final Long2ObjectMap <V> m ) {
-+   super( m );
-+   this.map = m;
-+  }
-+  public int size() { return map.size(); }
-+  public boolean containsKey( final long k ) { return map.containsKey( k ); }
-+  public boolean containsValue( final Object v ) { return map.containsValue( v ); }
-+  public V defaultReturnValue() { throw new UnsupportedOperationException(); }
-+  public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
-+  public V put( final long k, final V v ) { throw new UnsupportedOperationException(); }
-+  //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { throw new UnsupportedOperationException(); }
-+  public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
-+  public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.unmodifiable( map.long2ObjectEntrySet() ); return entries; }
-+  public LongSet keySet() { if ( keys == null ) keys = LongSets.unmodifiable( map.keySet() ); return keys; }
-+  public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.unmodifiable( map.values() ); return values; }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return map.toString(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final long k ) { throw new UnsupportedOperationException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final long k ) { return map.get( k ); }
-+  public boolean containsKey( final Object ok ) { return map.containsKey( ok ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public V get( final Object k ) { return map.get( k ); }
-+  public boolean isEmpty() { return map.isEmpty(); }
-+  public ObjectSet<Map.Entry<Long, V>> entrySet() { return ObjectSets.unmodifiable( map.entrySet() ); }
-+ }
-+ /** Returns an unmodifiable type-specific map backed by the given type-specific map.
-+	 *
-+	 * @param m the map to be wrapped in an unmodifiable map.
-+	 * @return an unmodifiable view of the specified map.
-+	 * @see java.util.Collections#unmodifiableMap(Map)
-+	 */
-+ public static <V> Long2ObjectMap <V> unmodifiable( final Long2ObjectMap <V> m ) { return new UnmodifiableMap <V>( m ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
-+ * is specified at creation time.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Long2ObjectOpenCustomHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient long[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The hash strategy of this custom map. */
-+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient LongSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this.strategy = strategy;
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new long[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( expected, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( m.size(), f, strategy );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( m, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( m.size(), f, strategy );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param strategy the strategy.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( m, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( k.length, f, strategy );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param strategy the strategy.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Returns the hashing strategy.
-+	 *
-+	 * @return the hashing strategy of this custom hash map.
-+	 */
-+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
-+  return strategy;
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Long,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final long k, final V v) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final long k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Long ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).longValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  long curr;
-+  final long[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+  }
-+ }
-+
-+ public V remove( final long k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final long k = ((((Long)(ok)).longValue()));
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Long ok ) {
-+  if ( ok == null ) return null;
-+  final long k = ((ok).longValue());
-+  if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final long k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final long k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final long key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long getKey() {
-+   return (Long.valueOf(key[ index ]));
-+  }
-+  public long getLongKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   return ( strategy.equals( (key[ index ]), (((e.getKey()).longValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** An iterator over a hash map. */
-+ private class MapIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the entry with the null key. */
-+  boolean mustReturnNullKey = Long2ObjectOpenCustomHashMap.this.containsNullKey;
-+  /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
-+  LongArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNullKey ) {
-+    mustReturnNullKey = false;
-+    return last = n;
-+   }
-+   final long key[] = Long2ObjectOpenCustomHashMap.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     final long k = wrapped.getLong( - pos - 1 );
-+     int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+     while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
-+     return p;
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   long curr;
-+   final long[] key = Long2ObjectOpenCustomHashMap.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      value[ last ] = null;
-+      return;
-+     }
-+     slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+    value[ last ] = value[ pos ];
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    Long2ObjectOpenCustomHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public Long2ObjectMap.Entry <V> next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
-+  private final MapEntry entry = new MapEntry();
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   if ( ( strategy.equals( (k), (0) ) ) ) return ( Long2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   long curr;
-+   final long[] key = Long2ObjectOpenCustomHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   final V v = (e.getValue());
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   long curr;
-+   final long[] key = Long2ObjectOpenCustomHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (curr), (k) ) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( strategy.equals( (curr), (k) ) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Long2ObjectOpenCustomHashMap.this.clear();
-+  }
-+ }
-+ public FastEntrySet <V> long2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements LongIterator {
-+  public KeyIterator() { super(); }
-+  public long nextLong() { return key[ nextEntry() ]; }
-+  public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractLongSet {
-+  public LongIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( long k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( long k ) {
-+   final int oldSize = size;
-+   Long2ObjectOpenCustomHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Long2ObjectOpenCustomHashMap.this.clear();
-+  }
-+ }
-+ public LongSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Long2ObjectOpenCustomHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final long newKey[] = new long[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+  }
-+  newValue[ newN ] = value[ n ];
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectOpenCustomHashMap <V> clone() {
-+  Long2ObjectOpenCustomHashMap <V> c;
-+  try {
-+   c = (Long2ObjectOpenCustomHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  c.strategy = strategy;
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = ( strategy.hashCode(key[ i ]) );
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeLong( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final long key[] = this.key = new long[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  long k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readLong();
-+   v = (V) s.readObject();
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Map;
-+import java.util.Arrays;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectIterator;
-+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
-+/** A type-specific hash map with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a map. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class Long2ObjectOpenHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient long[] key;
-+ /** The array of values. */
-+ protected transient V[] value;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the key zero. */
-+ protected transient boolean containsNullKey;
-+ /** The current table size. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the key zero, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Cached set of entries. */
-+ protected transient FastEntrySet <V> entries;
-+ /** Cached set of keys. */
-+ protected transient LongSet keys;
-+ /** Cached collection of values. */
-+ protected transient ObjectCollection <V> values;
-+ /** Creates a new hash map.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectOpenHashMap( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new long[ n + 1 ];
-+  value = (V[]) new Object[ n + 1 ];
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash map.
-+	 */
-+ public Long2ObjectOpenHashMap( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public Long2ObjectOpenHashMap() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
-+	 *
-+	 * @param m a {@link Map} to be copied into the new hash map. 
-+	 */
-+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 * @param f the load factor.
-+	 */
-+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
-+  this( m.size(), f );
-+  putAll( m );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
-+	 *
-+	 * @param m a type-specific map to be copied into the new hash map. 
-+	 */
-+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m ) {
-+  this( m, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash map using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @param f the load factor.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectOpenHashMap( final long[] k, final V[] v, final float f ) {
-+  this( k.length, f );
-+  if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
-+  for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
-+ }
-+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
-+	 *
-+	 * @param k the array of keys of the new hash map.
-+	 * @param v the array of corresponding values in the new hash map.
-+	 * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
-+	 */
-+ public Long2ObjectOpenHashMap( final long[] k, final V[] v ) {
-+  this( k, v, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNullKey ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private V removeEntry( final int pos ) {
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = null;
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ private V removeNullEntry() {
-+  containsNullKey = false;
-+  final V oldValue = value[ n ];
-+  value[ n ] = null;
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return oldValue;
-+ }
-+ /** {@inheritDoc} */
-+ public void putAll(Map<? extends Long,? extends V> m) {
-+  if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
-+  else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
-+  super.putAll( m );
-+ }
-+ private int insert(final long k, final V v) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return n;
-+   containsNullKey = true;
-+   pos = n;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return pos;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return pos;
-+   }
-+  }
-+  key[ pos ] = k;
-+  value[ pos ] = v;
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return -1;
-+ }
-+ public V put(final long k, final V v) {
-+  final int pos = insert( k, v );
-+  if ( pos < 0 ) return defRetValue;
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return oldValue;
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+ public V put( final Long ok, final V ov ) {
-+  final V v = (ov);
-+  final int pos = insert( ((ok).longValue()), v );
-+  if ( pos < 0 ) return (this.defRetValue);
-+  final V oldValue = value[ pos ];
-+  value[ pos ] = v;
-+  return (oldValue);
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  long curr;
-+  final long[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     value[ last ] = null;
-+     return;
-+    }
-+    slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+   value[ last ] = value[ pos ];
-+  }
-+ }
-+
-+ public V remove( final long k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return removeNullEntry();
-+   return defRetValue;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+ /** {@inheritDoc}
-+	 * @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ @Override
-+
-+ public V remove( final Object ok ) {
-+  final long k = ((((Long)(ok)).longValue()));
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNullKey ) return (removeNullEntry());
-+   return (this.defRetValue);
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
-+  }
-+ }
-+ /** @deprecated Please use the corresponding type-specific method instead. */
-+ @Deprecated
-+ public V get( final Long ok ) {
-+  if ( ok == null ) return null;
-+  final long k = ((ok).longValue());
-+  if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
-+  if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
-+   if ( ( (k) == (curr) ) ) return (value[ pos ]);
-+  }
-+ }
-+
-+ public V get( final long k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
-+  if ( ( (k) == (curr) ) ) return value[ pos ];
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
-+   if ( ( (k) == (curr) ) ) return value[ pos ];
-+  }
-+ }
-+
-+ public boolean containsKey( final long k ) {
-+  if ( ( (k) == (0) ) ) return containsNullKey;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  // There's always an unused entry.
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ public boolean containsValue( final Object v ) {
-+  final V value[] = this.value;
-+  final long key[] = this.key;
-+  if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
-+  for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
-+  return false;
-+ }
-+ /* Removes all elements from this map.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNullKey = false;
-+  Arrays.fill( key, (0) );
-+  Arrays.fill( value, null );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** The entry class for a hash map does not record key and value, but
-+	 * rather the position in the hash table of the corresponding entry. This
-+	 * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
-+	 * the map */
-+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
-+  // The table index this entry refers to, or -1 if this entry has been deleted.
-+  int index;
-+  MapEntry( final int index ) {
-+   this.index = index;
-+  }
-+  MapEntry() {}
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long getKey() {
-+   return (Long.valueOf(key[ index ]));
-+  }
-+  public long getLongKey() {
-+      return key[ index ];
-+  }
-+  public V getValue() {
-+   return (value[ index ]);
-+  }
-+  public V setValue( final V v ) {
-+   final V oldValue = value[ index ];
-+   value[ index ] = v;
-+   return oldValue;
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean equals( final Object o ) {
-+   if (!(o instanceof Map.Entry)) return false;
-+   Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
-+  }
-+  public int hashCode() {
-+   return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
-+  }
-+  public String toString() {
-+   return key[ index ] + "=>" + value[ index ];
-+  }
-+ }
-+ /** An iterator over a hash map. */
-+ private class MapIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the entry with the null key. */
-+  boolean mustReturnNullKey = Long2ObjectOpenHashMap.this.containsNullKey;
-+  /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
-+  LongArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public int nextEntry() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNullKey ) {
-+    mustReturnNullKey = false;
-+    return last = n;
-+   }
-+   final long key[] = Long2ObjectOpenHashMap.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     final long k = wrapped.getLong( - pos - 1 );
-+     int p = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
-+     while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
-+     return p;
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   long curr;
-+   final long[] key = Long2ObjectOpenHashMap.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      value[ last ] = null;
-+      return;
-+     }
-+     slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+    value[ last ] = value[ pos ];
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    containsNullKey = false;
-+    value[ n ] = null;
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    Long2ObjectOpenHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+  public int skip( final int n ) {
-+   int i = n;
-+   while( i-- != 0 && hasNext() ) nextEntry();
-+   return n - i - 1;
-+  }
-+ }
-+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
-+  private MapEntry entry;
-+  public Long2ObjectMap.Entry <V> next() {
-+   return entry = new MapEntry( nextEntry() );
-+  }
-+  @Override
-+  public void remove() {
-+   super.remove();
-+   entry.index = -1; // You cannot use a deleted entry.
-+  }
-+ }
-+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
-+  private final MapEntry entry = new MapEntry();
-+  public MapEntry next() {
-+   entry.index = nextEntry();
-+   return entry;
-+  }
-+ }
-+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
-+   return new EntryIterator();
-+  }
-+  public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
-+   return new FastEntryIterator();
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean contains( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   if ( ( (k) == (0) ) ) return ( Long2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
-+   long curr;
-+   final long[] key = Long2ObjectOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   // There's always an unused entry.
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
-+   }
-+  }
-+  @SuppressWarnings("unchecked")
-+  public boolean remove( final Object o ) {
-+   if ( !( o instanceof Map.Entry ) ) return false;
-+   final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
-+   if ( e.getKey() == null ) return false;
-+   final long k = ((e.getKey()).longValue());
-+   final V v = (e.getValue());
-+   if ( ( (k) == (0) ) ) {
-+    if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
-+     removeNullEntry();
-+     return true;
-+    }
-+    return false;
-+   }
-+   long curr;
-+   final long[] key = Long2ObjectOpenHashMap.this.key;
-+   int pos;
-+   // The starting point.
-+   if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+   if ( ( (curr) == (k) ) ) {
-+    if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+     removeEntry( pos );
-+     return true;
-+    }
-+    return false;
-+   }
-+   while( true ) {
-+    if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+    if ( ( (curr) == (k) ) ) {
-+     if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
-+      removeEntry( pos );
-+      return true;
-+     }
-+    }
-+   }
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public void clear() {
-+   Long2ObjectOpenHashMap.this.clear();
-+  }
-+ }
-+ public FastEntrySet <V> long2ObjectEntrySet() {
-+  if ( entries == null ) entries = new MapEntrySet();
-+  return entries;
-+ }
-+ /** An iterator on keys.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return keys
-+	 * instead of entries.
-+	 */
-+ private final class KeyIterator extends MapIterator implements LongIterator {
-+  public KeyIterator() { super(); }
-+  public long nextLong() { return key[ nextEntry() ]; }
-+  public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
-+ }
-+ private final class KeySet extends AbstractLongSet {
-+  public LongIterator iterator() {
-+   return new KeyIterator();
-+  }
-+  public int size() {
-+   return size;
-+  }
-+  public boolean contains( long k ) {
-+   return containsKey( k );
-+  }
-+  public boolean remove( long k ) {
-+   final int oldSize = size;
-+   Long2ObjectOpenHashMap.this.remove( k );
-+   return size != oldSize;
-+  }
-+  public void clear() {
-+   Long2ObjectOpenHashMap.this.clear();
-+  }
-+ }
-+ public LongSet keySet() {
-+  if ( keys == null ) keys = new KeySet();
-+  return keys;
-+ }
-+ /** An iterator on values.
-+	 *
-+	 * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
-+	 * (and possibly their type-specific counterparts) so that they return values
-+	 * instead of entries.
-+	 */
-+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
-+  public ValueIterator() { super(); }
-+  public V next() { return value[ nextEntry() ]; }
-+ }
-+ public ObjectCollection <V> values() {
-+  if ( values == null ) values = new AbstractObjectCollection <V>() {
-+    public ObjectIterator <V> iterator() {
-+     return new ValueIterator();
-+    }
-+    public int size() {
-+     return size;
-+    }
-+    public boolean contains( Object v ) {
-+     return containsValue( v );
-+    }
-+    public void clear() {
-+     Long2ObjectOpenHashMap.this.clear();
-+    }
-+   };
-+  return values;
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes the map, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing. 
-+	 *
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this map if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this map in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing maps.  {@linkplain #clear() Clearing a
-+	 * map} leaves the table size untouched. If you are reusing a map
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient maps.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the map.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the map.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+ @SuppressWarnings("unchecked")
-+ protected void rehash( final int newN ) {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final long newKey[] = new long[ newN + 1 ];
-+  final V newValue[] = (V[]) new Object[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+   newValue[ pos ] = value[ i ];
-+  }
-+  newValue[ newN ] = value[ n ];
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+  this.value = newValue;
-+ }
-+ /** Returns a deep copy of this map. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash map; the data stored in the
-+	 * map, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this map.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public Long2ObjectOpenHashMap <V> clone() {
-+  Long2ObjectOpenHashMap <V> c;
-+  try {
-+   c = (Long2ObjectOpenHashMap <V>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.keys = null;
-+  c.values = null;
-+  c.entries = null;
-+  c.containsNullKey = containsNullKey;
-+  c.key = key.clone();
-+  c.value = value.clone();
-+  return c;
-+ }
-+ /** Returns a hash code for this map.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this map.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
-+   if ( this != value[ i ] )
-+    t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
-+   h += t;
-+   i++;
-+  }
-+  // Zero / null keys have hash zero.		
-+  if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final long key[] = this.key;
-+  final V value[] = this.value;
-+  final MapIterator i = new MapIterator();
-+  s.defaultWriteObject();
-+  for( int j = size, e; j-- != 0; ) {
-+   e = i.nextEntry();
-+   s.writeLong( key[ e ] );
-+   s.writeObject( value[ e ] );
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final long key[] = this.key = new long[ n + 1 ];
-+  final V value[] = this.value = (V[]) new Object[ n + 1 ];
-+  long k;
-+  V v;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readLong();
-+   v = (V) s.readObject();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNullKey = true;
-+   }
-+   else {
-+    pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
-+    while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
-+   }
-+   key[ pos ] = k;
-+   value[ pos ] = v;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectCollection;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #entrySet()},
-+ * {@link #keySet()}, {@link #values()},
-+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
-+ *
-+ * @see SortedMap
-+ */
-+public interface Long2ObjectSortedMap <V> extends Long2ObjectMap <V>, SortedMap<Long, V> {
-+ /** A sorted entry set providing fast iteration.
-+	 *
-+	 * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
-+	 * of a large number of entry objects. Some <code>fastutil</code>
-+	 * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
-+	 * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
-+	 * by returning always the same entry</em> (of course, mutated).
-+	 */
-+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Long2ObjectMap.Entry <V> >, FastEntrySet <V> {
-+  /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
-+		 *
-+		 * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
-+		 */
-+  public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( Long2ObjectMap.Entry <V> from );
-+ }
-+ /** Returns a sorted-set view of the mappings contained in this map.
-+	 *  Note that this specification strengthens the one given in the
-+	 *  corresponding type-specific unsorted map.
-+	 *
-+	 * @return a sorted-set view of the mappings contained in this map.
-+	 * @see Map#entrySet()
-+	 */
-+ ObjectSortedSet<Map.Entry<Long, V>> entrySet();
-+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
-+	 * Note that this specification strengthens the one given in the
-+	 * corresponding type-specific unsorted map.
-+	 *
-+	 * @return a type-specific sorted-set view of the mappings contained in this map.
-+	 * @see #entrySet()
-+	 */
-+ ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
-+ /** Returns a sorted-set view of the keys contained in this map.
-+	 *  Note that this specification strengthens the one given in the
-+	 *  corresponding type-specific unsorted map.
-+	 *
-+	 * @return a sorted-set view of the keys contained in this map.
-+	 * @see Map#keySet()
-+	 */
-+ LongSortedSet keySet();
-+ /** Returns a set view of the values contained in this map.
-+	 * <P>Note that this specification strengthens the one given in {@link Map#values()},
-+	 * which was already strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link SortedMap}.
-+	 *
-+	 * @return a set view of the values contained in this map.
-+	 * @see Map#values()
-+	 */
-+ ObjectCollection <V> values();
-+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
-+	 *
-+	 * @see SortedMap#comparator()
-+	 */
-+ LongComparator comparator();
-+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
-+	 *
-+	 * @see SortedMap#subMap(Object,Object)
-+	 */
-+ Long2ObjectSortedMap <V> subMap(Long fromKey, Long toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
-+	 *
-+	 * @see SortedMap#headMap(Object)
-+	 */
-+ Long2ObjectSortedMap <V> headMap(Long toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
-+	 *
-+	 *  <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
-+	 *
-+	 * @see SortedMap#tailMap(Object)
-+	 */
-+ Long2ObjectSortedMap <V> tailMap(Long fromKey);
-+ /**  Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
-+	 * @see SortedMap#subMap(Object,Object)
-+	 */
-+ Long2ObjectSortedMap <V> subMap(long fromKey, long toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
-+	 * @see SortedMap#headMap(Object)
-+	 */
-+ Long2ObjectSortedMap <V> headMap(long toKey);
-+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
-+	 * @see SortedMap#tailMap(Object)
-+	 */
-+ Long2ObjectSortedMap <V> tailMap(long fromKey);
-+ /**
-+	 * @see SortedMap#firstKey()
-+	 */
-+ long firstLongKey();
-+ /**
-+	 * @see SortedMap#lastKey()
-+	 */
-+ long lastLongKey();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
-+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
-+import java.util.Comparator;
-+import java.util.Map;
-+import java.util.SortedMap;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class Long2ObjectSortedMaps {
-+ private Long2ObjectSortedMaps() {}
-+ /** Returns a comparator for entries based on a given comparator on keys.
-+	 *
-+	 * @param comparator a comparator on keys.
-+	 * @return the associated comparator on entries.
-+	 */
-+ public static Comparator<? super Map.Entry<Long, ?>> entryComparator( final LongComparator comparator ) {
-+  return new Comparator<Map.Entry<Long, ?>>() {
-+   public int compare( Map.Entry<Long, ?> x, Map.Entry<Long, ?> y ) {
-+    return comparator.compare( x.getKey(), y.getKey() );
-+   }
-+  };
-+ }
-+ /** An immutable class representing an empty type-specific sorted map. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted map.
-+	 */
-+ public static class EmptySortedMap <V> extends Long2ObjectMaps.EmptyMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySortedMap() {}
-+  public LongComparator comparator() { return null; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
-+ 
-+  public LongSortedSet keySet() { return LongSortedSets.EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> headMap( final long to ) { return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> tailMap( final long from ) { return EMPTY_MAP; }
-+  public long firstLongKey() { throw new NoSuchElementException(); }
-+  public long lastLongKey() { throw new NoSuchElementException(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long firstKey() { return (Long.valueOf(firstLongKey())); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long lastKey() { return (Long.valueOf(lastLongKey())); }
-+ }
-+ /** An empty sorted map (immutable). It is serializable and cloneable. 
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
-+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
-+	 * @return an empty sorted map (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <V> Long2ObjectSortedMap <V> emptyMap() {
-+  return EMPTY_MAP;
-+ }
-+ /** An immutable class representing a type-specific singleton sorted map. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted map.
-+	 */
-+ public static class Singleton <V> extends Long2ObjectMaps.Singleton <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongComparator comparator;
-+  protected Singleton( final long key, final V value, LongComparator comparator ) {
-+   super( key, value );
-+   this.comparator = comparator;
-+  }
-+  protected Singleton( final long key, final V value ) {
-+   this( key, value, null );
-+  }
-+ 
-+  final int compare( final long k1, final long k2 ) {
-+   return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
-+  }
-+  public LongComparator comparator() { return comparator; }
-+ 
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Long2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
-+  public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.singleton( key, comparator ); return (LongSortedSet )keys; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> headMap( final long to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
-+  @SuppressWarnings("unchecked")
-+  public Long2ObjectSortedMap <V> tailMap( final long from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
-+  public long firstLongKey() { return key; }
-+  public long lastLongKey() { return key; }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long firstKey() { return (Long.valueOf(firstLongKey())); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long lastKey() { return (Long.valueOf(lastLongKey())); }
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> singleton( final Long key, V value ) {
-+  return new Singleton <V>( ((key).longValue()), (value) );
-+ }
-+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @param comparator the comparator to use in the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> singleton( final Long key, V value, LongComparator comparator ) {
-+  return new Singleton <V>( ((key).longValue()), (value), comparator );
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> singleton( final long key, final V value ) {
-+  return new Singleton <V>( key, value );
-+ }
-+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
-+	 *
-+	 * <P>Note that albeit the returned map is immutable, its default return value may be changed.
-+	 *
-+	 * @param key the only key of the returned sorted map.
-+	 * @param value the only value of the returned sorted map.
-+	 * @param comparator the comparator to use in the returned sorted map.
-+	 * @return a type-specific immutable sorted map containing just the pair <code>&lt;key,value&gt;</code>.
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> singleton( final long key, final V value, LongComparator comparator ) {
-+  return new Singleton <V>( key, value, comparator );
-+ }
-+  /** A synchronized wrapper class for sorted maps. */
-+ public static class SynchronizedSortedMap <V> extends Long2ObjectMaps.SynchronizedMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectSortedMap <V> sortedMap;
-+  protected SynchronizedSortedMap( final Long2ObjectSortedMap <V> m, final Object sync ) {
-+   super( m, sync );
-+   sortedMap = m;
-+  }
-+  protected SynchronizedSortedMap( final Long2ObjectSortedMap <V> m ) {
-+   super( m );
-+   sortedMap = m;
-+  }
-+  public LongComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } }
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.long2ObjectEntrySet(), sync ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
-+  public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.synchronize( sortedMap.keySet(), sync ); return (LongSortedSet )keys; }
-+  public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
-+  public Long2ObjectSortedMap <V> headMap( final long to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
-+  public Long2ObjectSortedMap <V> tailMap( final long from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
-+  public long firstLongKey() { synchronized( sync ) { return sortedMap.firstLongKey(); } }
-+  public long lastLongKey() { synchronized( sync ) { return sortedMap.lastLongKey(); } }
-+  public Long firstKey() { synchronized( sync ) { return sortedMap.firstKey(); } }
-+  public Long lastKey() { synchronized( sync ) { return sortedMap.lastKey(); } }
-+  public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
-+  public Long2ObjectSortedMap <V> headMap( final Long to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
-+  public Long2ObjectSortedMap <V> tailMap( final Long from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
-+ }
-+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map.
-+	 *
-+	 * @param m the sorted map to be wrapped in a synchronized sorted map.
-+	 * @return a synchronized view of the specified sorted map.
-+	 * @see java.util.Collections#synchronizedSortedMap(SortedMap)
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> synchronize( final Long2ObjectSortedMap <V> m ) { return new SynchronizedSortedMap <V>( m ); }
-+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map, using an assigned object to synchronize.
-+	 *
-+	 * @param m the sorted map to be wrapped in a synchronized sorted map.
-+	 * @param sync an object that will be used to synchronize the access to the sorted sorted map.
-+	 * @return a synchronized view of the specified sorted map.
-+	 * @see java.util.Collections#synchronizedSortedMap(SortedMap)
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> synchronize( final Long2ObjectSortedMap <V> m, final Object sync ) { return new SynchronizedSortedMap <V>( m, sync ); }
-+ /** An unmodifiable wrapper class for sorted maps. */
-+ public static class UnmodifiableSortedMap <V> extends Long2ObjectMaps.UnmodifiableMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final Long2ObjectSortedMap <V> sortedMap;
-+  protected UnmodifiableSortedMap( final Long2ObjectSortedMap <V> m ) {
-+   super( m );
-+   sortedMap = m;
-+  }
-+  public LongComparator comparator() { return sortedMap.comparator(); }
-+  public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.long2ObjectEntrySet() ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
-+  @SuppressWarnings({ "rawtypes", "unchecked" })
-+  public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
-+  public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.unmodifiable( sortedMap.keySet() ); return (LongSortedSet )keys; }
-+  public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
-+  public Long2ObjectSortedMap <V> headMap( final long to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
-+  public Long2ObjectSortedMap <V> tailMap( final long from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
-+  public long firstLongKey() { return sortedMap.firstLongKey(); }
-+  public long lastLongKey() { return sortedMap.lastLongKey(); }
-+  public Long firstKey() { return sortedMap.firstKey(); }
-+  public Long lastKey() { return sortedMap.lastKey(); }
-+  public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
-+  public Long2ObjectSortedMap <V> headMap( final Long to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
-+  public Long2ObjectSortedMap <V> tailMap( final Long from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
-+ }
-+ /** Returns an unmodifiable type-specific sorted map backed by the given type-specific sorted map.
-+	 *
-+	 * @param m the sorted map to be wrapped in an unmodifiable sorted map.
-+	 * @return an unmodifiable view of the specified sorted map.
-+	 * @see java.util.Collections#unmodifiableSortedMap(SortedMap)
-+	 */
-+ public static <V> Long2ObjectSortedMap <V> unmodifiable( final Long2ObjectSortedMap <V> m ) { return new UnmodifiableSortedMap <V>( m ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2010-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.io.Serializable;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based FIFO queue, supporting also deque operations.
-+ *
-+ * <P>Instances of this class represent a FIFO queue using a backing
-+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
-+ * to reduce its memory usage, if necessary.
-+ *
-+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
-+ */
-+public class LongArrayFIFOQueue extends AbstractLongPriorityQueue implements Serializable {
-+    private static final long serialVersionUID = 0L;
-+ /** The standard initial capacity of a queue. */
-+ public final static int INITIAL_CAPACITY = 4;
-+ /** The backing array. */
-+ protected transient long array[];
-+ /** The current (cached) length of {@link #array}. */
-+ protected transient int length;
-+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
-+ protected transient int start;
-+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
-+	 *  Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
-+ protected transient int end;
-+ /** Creates a new empty queue with given capacity.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+
-+ public LongArrayFIFOQueue( final int capacity ) {
-+  if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
-+  array = new long[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
-+  length = array.length;
-+ }
-+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
-+	 */
-+ public LongArrayFIFOQueue() {
-+  this( INITIAL_CAPACITY );
-+ }
-+ /** Returns <code>null</code> (FIFO queues have no comparator). 
-+	 * @return <code>null</code>.
-+	 */
-+ @Override
-+ public LongComparator comparator() {
-+  return null;
-+ }
-+ @Override
-+ public long dequeueLong() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  final long t = array[ start ];
-+  if ( ++start == length ) start = 0;
-+  reduce();
-+  return t;
-+ }
-+ /** Dequeues the last element from the queue.
-+	 *
-+	 * @return the dequeued element. 
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ public long dequeueLastLong() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  if ( end == 0 ) end = length;
-+  final long t = array[ --end ];
-+  reduce();
-+  return t;
-+ }
-+
-+ private final void resize( final int size, final int newLength ) {
-+  final long[] newArray = new long[ newLength ];
-+  if ( start >= end ) {
-+   if ( size != 0 ) {
-+    System.arraycopy( array, start, newArray, 0, length - start );
-+    System.arraycopy( array, 0, newArray, length - start, end );
-+   }
-+  }
-+  else System.arraycopy( array, start, newArray, 0, end - start );
-+  start = 0;
-+  end = size;
-+  array = newArray;
-+  length = newLength;
-+ }
-+ private final void expand() {
-+  resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
-+ }
-+ private final void reduce() {
-+  final int size = size();
-+  if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
-+ }
-+ @Override
-+ public void enqueue( long x ) {
-+  array[ end++ ] = x;
-+  if ( end == length ) end = 0;
-+  if ( end == start ) expand();
-+ }
-+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
-+	 */
-+ public void enqueueFirst( long x ) {
-+  if ( start == 0 ) start = length;
-+  array[ --start ] = x;
-+  if ( end == start ) expand();
-+ }
-+ /** Returns the first element of the queue. 
-+	 * @return the first element of the queue.	
-+	 */
-+ public long firstLong() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  return array[ start ];
-+ }
-+ /** Returns the last element of the queue. 
-+	 * @return the last element of the queue.	
-+	 */
-+ public long lastLong() {
-+  if ( start == end ) throw new NoSuchElementException();
-+  return array[ ( end == 0 ? length : end ) - 1 ];
-+ }
-+ @Override
-+ public void clear() {
-+  start = end = 0;
-+ }
-+ /** Trims the queue to the smallest possible size. */
-+
-+ public void trim() {
-+  final int size = size();
-+  final long[] newArray =
-+           new long[ size + 1 ];
-+  if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
-+  else {
-+   System.arraycopy( array, start, newArray, 0, length - start );
-+   System.arraycopy( array, 0, newArray, length - start, end );
-+  }
-+  start = 0;
-+  length = ( end = size ) + 1;
-+  array = newArray;
-+ }
-+ @Override
-+ public int size() {
-+  final int apparentLength = end - start;
-+  return apparentLength >= 0 ? apparentLength : length + apparentLength;
-+ }
-+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  int size = size();
-+  s.writeInt( size );
-+  for( int i = start; size-- != 0; ) {
-+   s.writeLong( array[ i++ ] );
-+   if ( i == length ) i = 0;
-+  }
-+ }
-+
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  end = s.readInt();
-+  array = new long[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
-+  for( int i = 0; i < end; i++ ) array[ i ] = s.readLong();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.RandomAccess;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>This class implements a lightweight, fast, open, optimized,
-+ * reuse-oriented version of array-based lists. Instances of this class
-+ * represent a list with an array that is enlarged as needed when new entries
-+ * are created (by doubling its current length), but is
-+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
-+ * {@linkplain #trim() trimming methods} lets you control the size of the
-+ * backing array; this is particularly useful if you reuse instances of this class.
-+ * Range checks are equivalent to those of {@link java.util}'s classes, but
-+ * they are delayed as much as possible. The backing array is exposed by the
-+ * {@link #elements()} method.
-+ *
-+ * <p>This class implements the bulk methods <code>removeElements()</code>,
-+ * <code>addElements()</code> and <code>getElements()</code> using
-+ * high-performance system calls (e.g., {@link
-+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
-+ * expensive loops.
-+ *
-+ * @see java.util.ArrayList
-+ */
-+public class LongArrayList extends AbstractLongList implements RandomAccess, Cloneable, java.io.Serializable {
-+ private static final long serialVersionUID = -7046029254386353130L;
-+ /** The initial default capacity of an array list. */
-+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
-+ /** The backing array. */
-+ protected transient long a[];
-+ /** The current actual size of the list (never greater than the backing-array length). */
-+ protected int size;
-+ private static final boolean ASSERTS = false;
-+ /** Creates a new array list using a given array.
-+	 *
-+	 * <P>This constructor is only meant to be used by the wrapping methods.
-+	 *
-+	 * @param a the array that will be used to back this array list.
-+	 */
-+ @SuppressWarnings("unused")
-+ protected LongArrayList( final long a[], boolean dummy ) {
-+  this.a = a;
-+ }
-+ /** Creates a new array list with given capacity.
-+	 *
-+	 * @param capacity the initial capacity of the array list (may be 0).
-+	 */
-+
-+ public LongArrayList( final int capacity ) {
-+  if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
-+  a = new long[ capacity ];
-+ }
-+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
-+	 */
-+ public LongArrayList() {
-+  this( DEFAULT_INITIAL_CAPACITY );
-+ }
-+ /** Creates a new array list and fills it with a given collection.
-+	 *
-+	 * @param c a collection that will be used to fill the array list.
-+	 */
-+ public LongArrayList( final Collection<? extends Long> c ) {
-+  this( c.size() );
-+  size = LongIterators.unwrap( LongIterators.asLongIterator( c.iterator() ), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection that will be used to fill the array list.
-+	 */
-+ public LongArrayList( final LongCollection c ) {
-+  this( c.size() );
-+  size = LongIterators.unwrap( c.iterator(), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific list.
-+	 *
-+	 * @param l a type-specific list that will be used to fill the array list.
-+	 */
-+ public LongArrayList( final LongList l ) {
-+  this( l.size() );
-+  l.getElements( 0, a, 0, size = l.size() );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 */
-+ public LongArrayList( final long a[] ) {
-+  this( a, 0, a.length );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 */
-+ public LongArrayList( final long a[], final int offset, final int length ) {
-+  this( length );
-+  System.arraycopy( a, offset, this.a, 0, length );
-+  size = length;
-+ }
-+ /** Creates a new array list and fills it with the elements returned by an iterator..
-+	 *
-+	 * @param i an iterator whose returned elements will fill the array list.
-+	 */
-+ public LongArrayList( final Iterator<? extends Long> i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.next() );
-+ }
-+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
-+	 *
-+	 * @param i a type-specific iterator whose returned elements will fill the array list.
-+	 */
-+ public LongArrayList( final LongIterator i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.nextLong() );
-+ }
-+ /** Returns the backing array of this list.
-+	 *
-+	 * @return the backing array.
-+	 */
-+ public long[] elements() {
-+  return a;
-+ }
-+ /** Wraps a given array into an array list of given size.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @param length the length of the resulting array list.
-+	 * @return a new array list of the given size, wrapping the given array.
-+	 */
-+ public static LongArrayList wrap( final long a[], final int length ) {
-+  if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
-+  final LongArrayList l = new LongArrayList ( a, false );
-+  l.size = length;
-+  return l;
-+ }
-+ /** Wraps a given array into an array list.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @return a new array list wrapping the given array.
-+	 */
-+ public static LongArrayList wrap( final long a[] ) {
-+  return wrap( a, a.length );
-+ }
-+ /** Ensures that this array list can contain the given number of entries without resizing.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+
-+ public void ensureCapacity( final int capacity ) {
-+  a = LongArrays.ensureCapacity( a, capacity, size );
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
-+	 * and in case enlarging it at least by a factor of two.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+
-+ private void grow( final int capacity ) {
-+  a = LongArrays.grow( a, capacity, size );
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public void add( final int index, final long k ) {
-+  ensureIndex( index );
-+  grow( size + 1 );
-+  if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
-+  a[ index ] = k;
-+  size++;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public boolean add( final long k ) {
-+  grow( size + 1 );
-+  a[ size++ ] = k;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public long getLong( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  return a[ index ];
-+ }
-+ public int indexOf( final long k ) {
-+  for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public int lastIndexOf( final long k ) {
-+  for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public long removeLong( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  final long old = a[ index ];
-+  size--;
-+  if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
-+  if ( ASSERTS ) assert size <= a.length;
-+  return old;
-+ }
-+ public boolean rem( final long k ) {
-+  int index = indexOf( k );
-+  if ( index == -1 ) return false;
-+  removeLong( index );
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public long set( final int index, final long k ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  long old = a[ index ];
-+  a[ index ] = k;
-+  return old;
-+ }
-+ public void clear() {
-+  size = 0;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public void size( final int size ) {
-+  if ( size > a.length ) ensureCapacity( size );
-+  if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
-+  this.size = size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Trims this array list so that the capacity is equal to the size. 
-+	 *
-+	 * @see java.util.ArrayList#trimToSize()
-+	 */
-+ public void trim() {
-+  trim( 0 );
-+ }
-+ /** Trims the backing array if it is too large.
-+	 * 
-+	 * If the current array length is smaller than or equal to
-+	 * <code>n</code>, this method does nothing. Otherwise, it trims the
-+	 * array length to the maximum between <code>n</code> and {@link #size()}.
-+	 *
-+	 * <P>This method is useful when reusing lists.  {@linkplain #clear() Clearing a
-+	 * list} leaves the array length untouched. If you are reusing a list
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large array just
-+	 * because of a few large transient lists.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 */
-+
-+ public void trim( final int n ) {
-+  // TODO: use Arrays.trim() and preserve type only if necessary
-+  if ( n >= a.length || size == a.length ) return;
-+  final long t[] = new long[ Math.max( n, size ) ];
-+  System.arraycopy( a, 0, t, 0, size );
-+  a = t;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+    /** Copies element of this type-specific list into the given array using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final long[] a, final int offset, final int length ) {
-+  LongArrays.ensureOffsetLength( a, offset, length );
-+  System.arraycopy( this.a, from, a, offset, length );
-+ }
-+ /** Removes elements of this type-specific list using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
-+  System.arraycopy( a, to, a, from, size - to );
-+  size -= ( to - from );
-+ }
-+ /** Adds elements to this type-specific list using optimized system calls.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( final int index, final long a[], final int offset, final int length ) {
-+  ensureIndex( index );
-+  LongArrays.ensureOffsetLength( a, offset, length );
-+  grow( size + length );
-+  System.arraycopy( this.a, index, this.a, index + length, size - index );
-+  System.arraycopy( a, offset, this.a, index, length );
-+  size += length;
-+ }
-+ public long[] toLongArray( long a[] ) {
-+  if ( a == null || a.length < size ) a = new long[ size ];
-+  System.arraycopy( this.a, 0, a, 0, size );
-+  return a;
-+ }
-+ public boolean addAll( int index, final LongCollection c ) {
-+  ensureIndex( index );
-+  int n = c.size();
-+  if ( n == 0 ) return false;
-+  grow( size + n );
-+  if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
-+  final LongIterator i = c.iterator();
-+  size += n;
-+  while( n-- != 0 ) a[ index++ ] = i.nextLong();
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public boolean addAll( final int index, final LongList l ) {
-+  ensureIndex( index );
-+  final int n = l.size();
-+  if ( n == 0 ) return false;
-+  grow( size + n );
-+  if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
-+  l.getElements( 0, a, index, n );
-+  size += n;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ @Override
-+ public boolean removeAll( final LongCollection c ) {
-+  final long[] a = this.a;
-+  int j = 0;
-+  for( int i = 0; i < size; i++ )
-+   if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
-+  final boolean modified = size != j;
-+  size = j;
-+  return modified;
-+ }
-+ @Override
-+ public boolean removeAll( final Collection<?> c ) {
-+  final long[] a = this.a;
-+  int j = 0;
-+  for( int i = 0; i < size; i++ )
-+   if ( ! c.contains( (Long.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
-+  final boolean modified = size != j;
-+  size = j;
-+  return modified;
-+ }
-+ public LongListIterator listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractLongListIterator () {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < size; }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
-+    public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( long k ) {
-+     LongArrayList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( long k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     LongArrayList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     LongArrayList.this.removeLong( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public LongArrayList clone() {
-+  LongArrayList c = new LongArrayList ( size );
-+  System.arraycopy( a, 0, c.a, 0, size );
-+  c.size = size;
-+  return c;
-+ }
-+    /** Compares this type-specific array list to another one.
-+	 *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+	 * @param l a type-specific array list.
-+     * @return true if the argument contains the same elements of this type-specific array list.
-+	 */
-+ public boolean equals( final LongArrayList l ) {
-+  if ( l == this ) return true;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  final long[] a1 = a;
-+  final long[] a2 = l.a;
-+  while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
-+  return true;
-+ }
-+    /** Compares this array list to another array list.
-+     *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+     * @param l an array list.
-+     * @return a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     */
-+
-+ public int compareTo( final LongArrayList l ) {
-+  final int s1 = size(), s2 = l.size();
-+  final long a1[] = a, a2[] = l.a;
-+  long e1, e2;
-+  int r, i;
-+  for( i = 0; i < s1 && i < s2; i++ ) {
-+   e1 = a1[ i ];
-+   e2 = a2[ i ];
-+   if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
-+  }
-+  return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
-+ }
-+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
-+ }
-+
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = new long[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based priority queue.
-+ *
-+ * <P>Instances of this class represent a priority queue using a backing
-+ * array&mdash;all operations are performed directly on the array. The array is
-+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
-+ * to reduce its size, if necessary.
-+ *
-+ * <P>This implementation is extremely inefficient, but it is difficult to beat
-+ * when the size of the queue is very small.
-+ */
-+public class LongArrayPriorityQueue extends AbstractLongPriorityQueue implements java.io.Serializable {
-+ private static final long serialVersionUID = 1L;
-+ /** The backing array. */
-+
-+ protected transient long array[] = LongArrays.EMPTY_ARRAY;
-+ /** The number of elements in this queue. */
-+ protected int size;
-+ /** The type-specific comparator used in this queue. */
-+ protected LongComparator c;
-+ /** The first index, cached, if {@link #firstIndexValid} is true. */
-+ transient protected int firstIndex;
-+ /** Whether {@link #firstIndex} contains a valid value. */
-+ transient protected boolean firstIndexValid;
-+ /** Creates a new empty queue with a given capacity and comparator.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+
-+ public LongArrayPriorityQueue( int capacity, LongComparator c ) {
-+  if ( capacity > 0 ) this.array = new long[ capacity ];
-+  this.c = c;
-+ }
-+ /** Creates a new empty queue with a given capacity and using the natural order.
-+	 *
-+	 * @param capacity the initial capacity of this queue.
-+	 */
-+ public LongArrayPriorityQueue( int capacity ) {
-+  this( capacity, null );
-+ }
-+ /** Creates a new empty queue with a given comparator.
-+	 *
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public LongArrayPriorityQueue( LongComparator c ) {
-+  this( 0, c );
-+ }
-+ /** Creates a new empty queue using the natural order. 
-+	 */
-+ public LongArrayPriorityQueue() {
-+  this( 0, null );
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public LongArrayPriorityQueue( final long[] a, int size, final LongComparator c ) {
-+  this( c );
-+  this.array = a;
-+  this.size = size;
-+ }
-+ /** Wraps a given array in a queue using a given comparator.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param c the comparator used in this queue, or <code>null</code> for the natural order.
-+	 */
-+ public LongArrayPriorityQueue( final long[] a, final LongComparator c ) {
-+  this( a, a.length, c );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 * @param size the number of elements to be included in the queue.
-+	 */
-+ public LongArrayPriorityQueue( final long[] a, int size ) {
-+  this( a, size, null );
-+ }
-+ /** Wraps a given array in a queue using the natural order.
-+	 *
-+	 * <P>The queue returned by this method will be backed by the given array.
-+	 *
-+	 * @param a an array.
-+	 */
-+ public LongArrayPriorityQueue( final long[] a ) {
-+  this( a, a.length );
-+ }
-+ /** Returns the index of the smallest element. */
-+
-+ private int findFirst() {
-+  if ( firstIndexValid ) return this.firstIndex;
-+  firstIndexValid = true;
-+  int i = size;
-+  int firstIndex = --i;
-+  long first = array[ firstIndex ];
-+  if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
-+  else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
-+  return this.firstIndex = firstIndex;
-+ }
-+ private void ensureNonEmpty() {
-+  if ( size == 0 ) throw new NoSuchElementException();
-+ }
-+
-+ public void enqueue( long x ) {
-+  if ( size == array.length ) array = LongArrays.grow( array, size + 1 );
-+  if ( firstIndexValid ) {
-+   if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
-+   else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
-+  }
-+  else firstIndexValid = false;
-+  array[ size++ ] = x;
-+ }
-+ public long dequeueLong() {
-+  ensureNonEmpty();
-+  final int first = findFirst();
-+  final long result = array[ first ];
-+  System.arraycopy( array, first + 1, array, first, --size - first );
-+  firstIndexValid = false;
-+  return result;
-+ }
-+ public long firstLong() {
-+  ensureNonEmpty();
-+  return array[ findFirst() ];
-+ }
-+ public void changed() {
-+  ensureNonEmpty();
-+  firstIndexValid = false;
-+ }
-+ public int size() { return size; }
-+ public void clear() {
-+  size = 0;
-+  firstIndexValid = false;
-+ }
-+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
-+	 */
-+ public void trim() {
-+  array = LongArrays.trim( array, size );
-+ }
-+ public LongComparator comparator() { return c; }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  s.writeInt( array.length );
-+  for( int i = 0; i < size; i++ ) s.writeLong( array[ i ] );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  array = new long[ s.readInt() ];
-+  for( int i = 0; i < size; i++ ) array[ i ] = s.readLong();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2007-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/** A simple, brute-force implementation of a set based on a backing array.
-+ *
-+ * <p>The main purpose of this
-+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very 
-+ * small number of items: just put them into an array and scan linearly to find an item.
-+ */
-+public class LongArraySet extends AbstractLongSet implements java.io.Serializable, Cloneable {
-+ private static final long serialVersionUID = 1L;
-+ /** The backing array (valid up to {@link #size}, excluded). */
-+ private transient long[] a;
-+ /** The number of valid entries in {@link #a}. */
-+ private int size;
-+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
-+	 * 
-+	 * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 */
-+ public LongArraySet( final long[] a ) {
-+  this.a = a;
-+  size = a.length;
-+ }
-+ /** Creates a new empty array set.
-+	 */
-+ public LongArraySet() {
-+  this.a = LongArrays.EMPTY_ARRAY;
-+ }
-+ /** Creates a new empty array set of given initial capacity.
-+	 * 
-+	 * @param capacity the initial capacity.
-+	 */
-+ public LongArraySet( final int capacity ) {
-+  this.a = new long[ capacity ];
-+ }
-+ /** Creates a new array set copying the contents of a given collection.
-+	 * @param c a collection.
-+	 */
-+ public LongArraySet( LongCollection c ) {
-+  this( c.size () );
-+  addAll( c );
-+ }
-+ /** Creates a new array set copying the contents of a given set.
-+	 * @param c a collection.
-+	 */
-+ public LongArraySet( final Collection<? extends Long> c ) {
-+  this( c.size() );
-+  addAll( c );
-+ }
-+ /** Creates a new array set using the given backing array and the given number of elements of the array.
-+	 *
-+	 * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 * @param size the number of valid elements in <code>a</code>.
-+	 */
-+ public LongArraySet( final long[] a, final int size ) {
-+  this.a = a;
-+  this.size = size;
-+  if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
-+ }
-+ private int findKey( final long o ) {
-+  for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
-+  return -1;
-+ }
-+ @Override
-+
-+ public LongIterator iterator() {
-+  return new AbstractLongIterator () {
-+   int next = 0;
-+   public boolean hasNext() {
-+    return next < size;
-+   }
-+   public long nextLong() {
-+    if ( ! hasNext() ) throw new NoSuchElementException();
-+    return a[ next++ ];
-+   }
-+   public void remove() {
-+    final int tail = size-- - next--;
-+    System.arraycopy( a, next + 1, a, next, tail );
-+   }
-+  };
-+ }
-+ public boolean contains( final long k ) {
-+  return findKey( k ) != -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ @Override
-+ public boolean remove( final long k ) {
-+  final int pos = findKey( k );
-+  if ( pos == -1 ) return false;
-+  final int tail = size - pos - 1;
-+  for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
-+  size--;
-+  return true;
-+ }
-+ @Override
-+ public boolean add( final long k ) {
-+  final int pos = findKey( k );
-+  if ( pos != -1 ) return false;
-+  if ( size == a.length ) {
-+   final long[] b = new long[ size == 0 ? 2 : size * 2 ];
-+   for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
-+   a = b;
-+  }
-+  a[ size++ ] = k;
-+  return true;
-+ }
-+ @Override
-+ public void clear() {
-+  size = 0;
-+ }
-+ @Override
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public LongArraySet clone() {
-+  LongArraySet c;
-+  try {
-+   c = (LongArraySet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.a = a.clone();
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
-+ }
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = new long[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ *
-+ *
-+ *
-+ * For the sorting and binary search code:
-+ *
-+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
-+ *
-+ *   Permission to use, copy, modify, distribute and sell this software and
-+ *   its documentation for any purpose is hereby granted without fee,
-+ *   provided that the above copyright notice appear in all copies and that
-+ *   both that copyright notice and this permission notice appear in
-+ *   supporting documentation. CERN makes no representations about the
-+ *   suitability of this software for any purpose. It is provided "as is"
-+ *   without expressed or implied warranty. 
-+ */
-+package it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Arrays;
-+import it.unimi.dsi.fastutil.Hash;
-+import java.util.Random;
-+import java.util.concurrent.ForkJoinPool;
-+import java.util.concurrent.RecursiveAction;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+import java.util.concurrent.Callable;
-+import java.util.concurrent.ExecutorCompletionService;
-+import java.util.concurrent.ExecutorService;
-+import java.util.concurrent.Executors;
-+import java.util.concurrent.LinkedBlockingQueue;
-+import java.util.concurrent.atomic.AtomicInteger;
-+/** A class providing static methods and objects that do useful things with type-specific arrays.
-+ *
-+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
-+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
-+ * arrays much like array lists. This can be very useful when efficiency (or
-+ * syntactic simplicity) reasons make array lists unsuitable.
-+ *
-+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
-+ * contain several methods make it possible to load and save arrays of primitive types as sequences
-+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
-+ *
-+ * <h2>Sorting</h2>
-+ *
-+ * <p>There are several sorting methods available. The main theme is that of letting you choose
-+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
-+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
-+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
-+ * to sort an array using the values in another array as comparator.
-+ *
-+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
-+ *
-+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
-+ * on random-looking data. In
-+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
-+ * exploits parallelism better.
-+ *
-+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated), 
-+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
-+ * are about 50% faster than the classical single-pivot implementation used here.
-+ *
-+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
-+ * with your data distribution and on your architecture.
-+ * 
-+ * @see java.util.Arrays
-+ */
-+public class LongArrays {
-+ private LongArrays() {}
-+ /** A static, final, empty array. */
-+ public final static long[] EMPTY_ARRAY = {};
-+ /** Ensures that an array can contain the given number of entries.
-+	 *
-+	 * <P>If you cannot foresee whether this array will need again to be
-+	 * enlarged, you should probably use <code>grow()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>array.length</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static long[] ensureCapacity( final long[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final long t[] =
-+    new long[ length ];
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>preserve</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static long[] ensureCapacity( final long[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final long t[] =
-+    new long[ length ];
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>array.length</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static long[] grow( final long[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final long t[] =
-+    new long[ newLength ];
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length, preserving just a part of the array.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>preserve</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static long[] grow( final long[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final long t[] =
-+    new long[ newLength ];
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Trims the given array to the given length.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new maximum length for the array.
-+	 * @return <code>array</code>, if it contains <code>length</code>
-+	 * entries or less; otherwise, an array with
-+	 * <code>length</code> entries whose entries are the same as
-+	 * the first <code>length</code> entries of <code>array</code>.
-+	 * 
-+	 */
-+ public static long[] trim( final long[] array, final int length ) {
-+  if ( length >= array.length ) return array;
-+  final long t[] =
-+   length == 0 ? EMPTY_ARRAY : new long[ length ];
-+  System.arraycopy( array, 0, t, 0, length );
-+  return t;
-+ }
-+ /** Sets the length of the given array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new length for the array.
-+	 * @return <code>array</code>, if it contains exactly <code>length</code>
-+	 * entries; otherwise, if it contains <em>more</em> than
-+	 * <code>length</code> entries, an array with <code>length</code> entries
-+	 * whose entries are the same as the first <code>length</code> entries of
-+	 * <code>array</code>; otherwise, an array with <code>length</code> entries
-+	 * whose first <code>array.length</code> entries are the same as those of
-+	 * <code>array</code>.
-+	 * 
-+	 */
-+ public static long[] setLength( final long[] array, final int length ) {
-+  if ( length == array.length ) return array;
-+  if ( length < array.length ) return trim( array, length );
-+  return ensureCapacity( array, length );
-+ }
-+ /** Returns a copy of a portion of an array.
-+	 *
-+	 * @param array an array.
-+	 * @param offset the first element to copy.
-+	 * @param length the number of elements to copy.
-+	 * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
-+	 */
-+ public static long[] copy( final long[] array, final int offset, final int length ) {
-+  ensureOffsetLength( array, offset, length );
-+  final long[] a =
-+   length == 0 ? EMPTY_ARRAY : new long[ length ];
-+  System.arraycopy( array, offset, a, 0, length );
-+  return a;
-+ }
-+ /** Returns a copy of an array.
-+	 *
-+	 * @param array an array.
-+	 * @return a copy of <code>array</code>.
-+	 */
-+ public static long[] copy( final long[] array ) {
-+  return array.clone();
-+ }
-+ /** Fills the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param value the new value for all elements of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static void fill( final long[] array, final long value ) {
-+  int i = array.length;
-+  while( i-- != 0 ) array[ i ] = value;
-+ }
-+ /** Fills a portion of the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param from the starting index of the portion to fill (inclusive).
-+	 * @param to the end index of the portion to fill (exclusive).
-+	 * @param value the new value for all elements of the specified portion of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static void fill( final long[] array, final int from, int to, final long value ) {
-+  ensureFromTo( array, from, to );
-+  if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
-+  else for( int i = from; i < to; i++ ) array[ i ] = value;
-+ }
-+ /** Returns true if the two arrays are elementwise equal.
-+	 *
-+	 * @param a1 an array.
-+	 * @param a2 another array.
-+	 * @return true if the two arrays are of the same length, and their elements are equal.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
-+	 */
-+ @Deprecated
-+ public static boolean equals( final long[] a1, final long a2[] ) {
-+  int i = a1.length;
-+  if ( i != a2.length ) return false;
-+  while( i-- != 0 ) if (! ( (a1[ i ]) == (a2[ i ]) ) ) return false;
-+  return true;
-+ }
-+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param from a start index (inclusive).
-+	 * @param to an end index (exclusive).
-+	 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
-+	 */
-+ public static void ensureFromTo( final long[] a, final int from, final int to ) {
-+  Arrays.ensureFromTo( a.length, from, to );
-+ }
-+ /** Ensures that a range given by an offset and a length fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param offset a start index.
-+	 * @param length a length (the number of elements in the range).
-+	 * @throws IllegalArgumentException if <code>length</code> is negative.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
-+	 */
-+ public static void ensureOffsetLength( final long[] a, final int offset, final int length ) {
-+  Arrays.ensureOffsetLength( a.length, offset, length );
-+ }
-+ /** Ensures that two arrays are of the same length.
-+	 *
-+	 * @param a an array.
-+	 * @param b another array.
-+	 * @throws IllegalArgumentException if the two argument arrays are not of the same length.
-+	 */
-+ public static void ensureSameLength( final long[] a, final long[] b ) {
-+  if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
-+ }
-+ private static final int QUICKSORT_NO_REC = 16;
-+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
-+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
-+ private static final int MERGESORT_NO_REC = 16;
-+ /** Swaps two elements of an anrray.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 */
-+ public static void swap( final long x[], final int a, final int b ) {
-+  final long t = x[ a ];
-+  x[ a ] = x[ b ];
-+  x[ b ] = t;
-+ }
-+ /** Swaps two sequences of elements of an array.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 * @param n the number of elements to exchange starting at {@code a} and {@code b}.
-+	 */
-+ public static void swap( final long[] x, int a, int b, final int n ) {
-+  for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
-+ }
-+ private static int med3( final long x[], final int a, final int b, final int c, LongComparator comp ) {
-+  final int ab = comp.compare( x[ a ], x[ b ] );
-+  final int ac = comp.compare( x[ a ], x[ c ] );
-+  final int bc = comp.compare( x[ b ], x[ c ] );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static void selectionSort( final long[] a, final int from, final int to, final LongComparator comp ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
-+   if ( m != i ) {
-+    final long u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+ private static void insertionSort( final long[] a, final int from, final int to, final LongComparator comp ) {
-+  for ( int i = from; ++i < to; ) {
-+   long t = a[ i ];
-+   int j = i;
-+   for ( long u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static void quickSort( final long[] x, final int from, final int to, final LongComparator comp ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to, comp );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s, comp );
-+   m = med3( x, m - s, m, m + s, comp );
-+   n = med3( x, n - 2 * s, n - s, n, comp );
-+  }
-+  m = med3( x, l, m, n, comp ); // Mid-size, med of 3
-+  final long v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while( true ) {
-+   int comparison;
-+   while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static void quickSort( final long[] x, final LongComparator comp ) {
-+  quickSort( x, 0, x.length, comp );
-+ }
-+ protected static class ForkJoinQuickSortComp extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final long[] x;
-+  private final LongComparator comp;
-+  public ForkJoinQuickSortComp( final long[] x , final int from , final int to, final LongComparator comp ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.comp = comp;
-+  }
-+  @Override
-+  protected void compute() {
-+   final long[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to, comp );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final long v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ), new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ) );
-+   else invokeAll( new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void parallelQuickSort( final long[] x, final int from, final int to, final LongComparator comp ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortComp ( x, from, to, comp ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void parallelQuickSort( final long[] x, final LongComparator comp ) {
-+  parallelQuickSort( x, 0, x.length, comp );
-+ }
-+
-+ private static int med3( final long x[], final int a, final int b, final int c ) {
-+  final int ab = ( Long.compare((x[ a ]),(x[ b ])) );
-+  final int ac = ( Long.compare((x[ a ]),(x[ c ])) );
-+  final int bc = ( Long.compare((x[ b ]),(x[ c ])) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+
-+ private static void selectionSort( final long[] a, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( ( (a[ j ]) < (a[ m ]) ) ) m = j;
-+   if ( m != i ) {
-+    final long u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+
-+ private static void insertionSort( final long[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   long t = a[ i ];
-+   int j = i;
-+   for ( long u = a[ j - 1 ]; ( (t) < (u) ); u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSort( final long[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, l, m, n ); // Mid-size, med of 3
-+  final long v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( Long.compare((x[ b ]),(v)) ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( Long.compare((x[ c ]),(v)) ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void quickSort( final long[] x ) {
-+  quickSort( x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final long[] x;
-+  public ForkJoinQuickSort( final long[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final long[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final long v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( Long.compare((x[ b ]),(v)) ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( Long.compare((x[ c ]),(v)) ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ), new ForkJoinQuickSort ( x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort ( x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSort( final long[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSort ( x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void parallelQuickSort( final long[] x ) {
-+  parallelQuickSort( x, 0, x.length );
-+ }
-+
-+ private static int med3Indirect( final int perm[], final long x[], final int a, final int b, final int c ) {
-+  final long aa = x[ perm[ a ] ];
-+  final long bb = x[ perm[ b ] ];
-+  final long cc = x[ perm[ c ] ];
-+  final int ab = ( Long.compare((aa),(bb)) );
-+  final int ac = ( Long.compare((aa),(cc)) );
-+  final int bc = ( Long.compare((bb),(cc)) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+
-+ private static void insertionSortIndirect( final int[] perm, final long[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = perm[ i ];
-+   int j = i;
-+   for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ); u = perm[ --j - 1 ] ) {
-+    perm[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   perm[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSortIndirect( final int[] perm, final long[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   insertionSortIndirect( perm, x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+  }
-+  m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
-+  final long v = x[ perm[ m ] ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( Long.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( Long.compare((x[ perm[ c ] ]),(v)) ) ) >=0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   IntArrays.swap( perm, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  IntArrays.swap( perm, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  IntArrays.swap( perm, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 */
-+ public static void quickSortIndirect( final int perm[], final long[] x ) {
-+  quickSortIndirect( perm, x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSortIndirect extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] perm;
-+  private final long[] x;
-+  public ForkJoinQuickSortIndirect( final int perm[], final long[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.perm = perm;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final long[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSortIndirect( perm, x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+   m = med3Indirect( perm, x, l, m, n );
-+   final long v = x[ perm[ m ] ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( Long.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( Long.compare((x[ perm[ c ] ]),(v)) ) ) >= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    IntArrays.swap( perm, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   IntArrays.swap( perm, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   IntArrays.swap( perm, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ), new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSortIndirect( final int[] perm, final long[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortIndirect ( perm, x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static void parallelQuickSortIndirect( final int perm[], final long[] x ) {
-+  parallelQuickSortIndirect( perm, x, 0, x.length );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 * @param from the index of the first element (inclusive) to be stabilized.
-+	 * @param to the index of the last element (exclusive) to be stabilized.
-+	 */
-+ public static void stabilize( final int perm[], final long[] x, final int from, final int to ) {
-+  int curr = from;
-+  for( int i = from + 1; i < to; i++ ) {
-+   if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
-+    if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
-+    curr = i;
-+   }
-+  }
-+  if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 */
-+ public static void stabilize( final int perm[], final long[] x ) {
-+  stabilize( perm, x, 0, perm.length );
-+ }
-+
-+ private static int med3( final long x[], final long[] y, final int a, final int b, final int c ) {
-+  int t;
-+  final int ab = ( t = ( Long.compare((x[ a ]),(x[ b ])) ) ) == 0 ? ( Long.compare((y[ a ]),(y[ b ])) ) : t;
-+  final int ac = ( t = ( Long.compare((x[ a ]),(x[ c ])) ) ) == 0 ? ( Long.compare((y[ a ]),(y[ c ])) ) : t;
-+  final int bc = ( t = ( Long.compare((x[ b ]),(x[ c ])) ) ) == 0 ? ( Long.compare((y[ b ]),(y[ c ])) ) : t;
-+  return ( ab < 0 ?
-+    ( bc < 0 ? b : ac < 0 ? c : a ) :
-+    ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static void swap( final long x[], final long[] y, final int a, final int b ) {
-+  final long t = x[ a ];
-+  final long u = y[ a ];
-+  x[ a ] = x[ b ];
-+  y[ a ] = y[ b ];
-+  x[ b ] = t;
-+  y[ b ] = u;
-+ }
-+ private static void swap( final long[] x, final long[] y, int a, int b, final int n ) {
-+  for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
-+ }
-+
-+ private static void selectionSort( final long[] a, final long[] b, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i, u;
-+   for( int j = i + 1; j < to; j++ )
-+    if ( ( u = ( Long.compare((a[ j ]),(a[ m ])) ) ) < 0 || u == 0 && ( (b[ j ]) < (b[ m ]) ) ) m = j;
-+   if ( m != i ) {
-+    long t = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = t;
-+    t = b[ i ];
-+    b[ i ] = b[ m ];
-+    b[ m ] = t;
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+
-+ public static void quickSort( final long[] x, final long[] y, final int from, final int to ) {
-+  final int len = to - from;
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, y, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, y, l, m, n ); // Mid-size, med of 3
-+  final long v = x[ m ], w = y[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while ( true ) {
-+   int comparison, t;
-+   while ( b <= c && ( comparison = ( t = ( Long.compare((x[ b ]),(v)) ) ) == 0 ? ( Long.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = ( t = ( Long.compare((x[ c ]),(v)) ) ) == 0 ? ( Long.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, y, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, y, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, y, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
-+ }
-+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static void quickSort( final long[] x, final long[] y ) {
-+  ensureSameLength( x, y );
-+  quickSort( x, y, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort2 extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final long[] x, y;
-+  public ForkJoinQuickSort2( final long[] x, final long[] y, final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.y = y;
-+  }
-+  @Override
-+ 
-+  protected void compute() {
-+   final long[] x = this.x;
-+   final long[] y = this.y;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, y, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+   m = med3( x, y, l, m, n );
-+   final long v = x[ m ], w = y[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison, t;
-+    while ( b <= c && ( comparison = ( t = ( Long.compare((x[ b ]),(v)) ) ) == 0 ? ( Long.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( t = ( Long.compare((x[ c ]),(v)) ) ) == 0 ? ( Long.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, y, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, y, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, y, b, to - s, s );
-+   s = b - a;
-+   t = d - c;
-+   // Recursively sort non-partition-elements
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ), new ForkJoinQuickSort2 ( x, y, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort2 ( x, y, to - t, to ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelQuickSort( final long[] x, final long[] y, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
-+  final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+  pool.invoke( new ForkJoinQuickSort2 ( x, y, from, to ) );
-+  pool.shutdown();
-+ }
-+ /** Sorts two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static void parallelQuickSort( final long[] x, final long[] y ) {
-+  ensureSameLength( x, y );
-+  parallelQuickSort( x, y, 0, x.length );
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated. 
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+
-+ public static void mergeSort( final long a[], final int from, final int to, final long supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to );
-+   return;
-+  }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, a );
-+  mergeSort( supp, mid, to, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( ( (supp[ mid - 1 ]) <= (supp[ mid ]) ) ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && ( (supp[ p ]) <= (supp[ q ]) ) ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void mergeSort( final long a[], final int from, final int to ) {
-+  mergeSort( a, from, to, a.clone() );
-+ }
-+ /**	Sorts an array according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void mergeSort( final long a[] ) {
-+  mergeSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+ public static void mergeSort( final long a[], final int from, final int to, LongComparator comp, final long supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to, comp );
-+   return;
-+     }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, comp, a );
-+  mergeSort( supp, mid, to, comp, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 *
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void mergeSort( final long a[], final int from, final int to, LongComparator comp ) {
-+  mergeSort( a, from, to, comp, a.clone() );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort.  An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static void mergeSort( final long a[], LongComparator comp ) {
-+  mergeSort( a, 0, a.length, comp );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+
-+ public static int binarySearch( final long[] a, int from, int to, final long key ) {
-+  long midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   if (midVal < key) from = mid + 1;
-+   else if (midVal > key) to = mid - 1;
-+   else return mid;
-+        }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final long[] a, final long key ) {
-+  return binarySearch( a, 0, a.length, key );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final long[] a, int from, int to, final long key, final LongComparator c ) {
-+  long midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   final int cmp = c.compare( midVal, key );
-+   if ( cmp < 0 ) from = mid + 1;
-+   else if (cmp > 0) to = mid - 1;
-+   else return mid; // key found
-+  }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static int binarySearch( final long[] a, final long key, final LongComparator c ) {
-+  return binarySearch( a, 0, a.length, key, c );
-+ }
-+ /** The size of a digit used during radix sort (must be a power of 2). */
-+ private static final int DIGIT_BITS = 8;
-+ /** The mask to extract a digit of {@link #DIGIT_BITS} bits. */
-+ private static final int DIGIT_MASK = ( 1 << DIGIT_BITS ) - 1;
-+ /** The number of digits per element. */
-+ private static final int DIGITS_PER_ELEMENT = Long.SIZE / DIGIT_BITS;
-+ private static final int RADIXSORT_NO_REC = 1024;
-+ private static final int PARALLEL_RADIXSORT_NO_FORK = 1024;
-+ /** This method fixes negative numbers so that the combination exponent/significand is lexicographically sorted. */
-+ /** Sorts the specified array using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation is significantly faster than quicksort 
-+	 * already at small sizes (say, more than 10000 elements), but it can only
-+	 * sort in ascending order. 
-+	 * 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void radixSort( final long[] a ) {
-+  radixSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified range of an array using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation is significantly faster than quicksort 
-+	 * already at small sizes (say, more than 10000 elements), but it can only
-+	 * sort in ascending order. 
-+	 * 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final long[] a, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   quickSort( a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ (int)((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    long t = a[ i ];
-+    c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while ( ( d = --pos[ c ] ) > i ) {
-+      final long z = t;
-+      t = a[ d ];
-+      a[ d ] = z;
-+      c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
-+     }
-+     a[ i ] = t;
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) quickSort( a, i, i + count[ c ] );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ protected final static class Segment {
-+  protected final int offset, length, level;
-+  protected Segment( final int offset, final int length, final int level ) {
-+   this.offset = offset;
-+   this.length = length;
-+   this.level = level;
-+  }
-+  @Override
-+  public String toString() {
-+   return "Segment [offset=" + offset + ", length=" + length + ", level=" + level + "]";
-+  }
-+ }
-+ protected final static Segment POISON_PILL = new Segment( -1, -1, -1 );
-+ /** Sorts the specified range of an array using parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelRadixSort( final long[] a, final int from, final int to ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   quickSort( a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
-+   public Void call() throws Exception {
-+    final int[] count = new int[ 1 << DIGIT_BITS ];
-+    final int[] pos = new int[ 1 << DIGIT_BITS ];
-+    for(;;) {
-+     if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
-+     final Segment segment = queue.take();
-+     if ( segment == POISON_PILL ) return null;
-+     final int first = segment.offset;
-+     final int length = segment.length;
-+     final int level = segment.level;
-+     final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+     final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+     // Count keys.
-+     for( int i = first + length; i-- != first; ) count[ (int)((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+     // Compute cumulative distribution
-+     int lastUsed = -1;
-+     for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+      if ( count[ i ] != 0 ) lastUsed = i;
-+      pos[ i ] = ( p += count[ i ] );
-+     }
-+     final int end = first + length - count[ lastUsed ];
-+     // i moves through the start of each block
-+     for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+      long t = a[ i ];
-+      c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
-+      if ( i < end ) {
-+       while( ( d = --pos[ c ] ) > i ) {
-+        final long z = t;
-+        t = a[ d ];
-+        a[ d ] = z;
-+        c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
-+       }
-+       a[ i ] = t;
-+      }
-+      if ( level < maxLevel && count[ c ] > 1 ) {
-+       if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, i, i + count[ c ] );
-+       else {
-+        queueSize.incrementAndGet();
-+        queue.add( new Segment( i, count[ c ], level + 1 ) );
-+       }
-+      }
-+     }
-+     queueSize.decrementAndGet();
-+    }
-+   }
-+  } );
-+  Throwable problem = null;
-+  for( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts the specified array using parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static void parallelRadixSort( final long[] a ) {
-+  parallelRadixSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified array using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final long[] a, final boolean stable ) {
-+  radixSortIndirect( perm, a, 0, perm.length, stable );
-+ }
-+ /** Sorts the specified array using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
-+	 * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final long[] a, final int from, final int to, final boolean stable ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   insertionSortIndirect( perm, a, from, to );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   if ( stable ) {
-+    for( int i = first + length; i-- != first; ) support[ --pos[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+    System.arraycopy( support, 0, perm, first, length );
-+    for( int i = 0, p = first; i <= lastUsed; i++ ) {
-+     if ( level < maxLevel && count[ i ] > 1 ) {
-+      if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, p, p + count[ i ] );
-+      else {
-+       offsetStack[ stackPos ] = p;
-+       lengthStack[ stackPos ] = count[ i ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+     p += count[ i ];
-+    }
-+    java.util.Arrays.fill( count, 0 );
-+   }
-+   else {
-+    final int end = first + length - count[ lastUsed ];
-+    // i moves through the start of each block
-+    for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+     int t = perm[ i ];
-+     c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+     if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+      while( ( d = --pos[ c ] ) > i ) {
-+       final int z = t;
-+       t = perm[ d ];
-+       perm[ d ] = z;
-+       c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+      }
-+      perm[ i ] = t;
-+     }
-+     if ( level < maxLevel && count[ c ] > 1 ) {
-+      if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, i, i + count[ c ] );
-+      else {
-+       offsetStack[ stackPos ] = i;
-+       lengthStack[ stackPos ] = count[ c ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of an array using parallel indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void parallelRadixSortIndirect( final int perm[], final long[] a, final int from, final int to, final boolean stable ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   radixSortIndirect( perm, a, from, to, stable );
-+   return;
-+  }
-+  final int maxLevel = DIGITS_PER_ELEMENT - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
-+   public Void call() throws Exception {
-+    final int[] count = new int[ 1 << DIGIT_BITS ];
-+    final int[] pos = new int[ 1 << DIGIT_BITS ];
-+    for(;;) {
-+     if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
-+     final Segment segment = queue.take();
-+     if ( segment == POISON_PILL ) return null;
-+     final int first = segment.offset;
-+     final int length = segment.length;
-+     final int level = segment.level;
-+     final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+     final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+     // Count keys.
-+     for( int i = first + length; i-- != first; ) count[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+     // Compute cumulative distribution
-+     int lastUsed = -1;
-+     for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+      if ( count[ i ] != 0 ) lastUsed = i;
-+      pos[ i ] = ( p += count[ i ] );
-+     }
-+     if ( stable ) {
-+      for( int i = first + length; i-- != first; ) support[ --pos[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+      System.arraycopy( support, first, perm, first, length );
-+      for( int i = 0, p = first; i <= lastUsed; i++ ) {
-+       if ( level < maxLevel && count[ i ] > 1 ) {
-+        if ( count[ i ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, p, p + count[ i ], stable );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( p, count[ i ], level + 1 ) );
-+        }
-+       }
-+       p += count[ i ];
-+      }
-+      java.util.Arrays.fill( count, 0 );
-+     }
-+     else {
-+      final int end = first + length - count[ lastUsed ];
-+      // i moves through the start of each block
-+      for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+       int t = perm[ i ];
-+       c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+       if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+        while( ( d = --pos[ c ] ) > i ) {
-+         final int z = t;
-+         t = perm[ d ];
-+         perm[ d ] = z;
-+         c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+        }
-+        perm[ i ] = t;
-+       }
-+       if ( level < maxLevel && count[ c ] > 1 ) {
-+        if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, i, i + count[ c ], stable );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( i, count[ c ], level + 1 ) );
-+        }
-+       }
-+      }
-+     }
-+     queueSize.decrementAndGet();
-+    }
-+   }
-+  } );
-+  Throwable problem = null;
-+  for( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts the specified array using parallel indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void parallelRadixSortIndirect( final int perm[], final long[] a, final boolean stable ) {
-+  parallelRadixSortIndirect( perm, a, 0, a.length, stable );
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using radix sort.
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 */
-+ public static void radixSort( final long[] a, final long[] b ) {
-+  ensureSameLength( a, b );
-+  radixSort( a, b, 0, a.length );
-+ }
-+ /** Sorts the specified range of elements of two arrays using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final long[] a, final long[] b, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   selectionSort( a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    long t = a[ i ];
-+    long u = b[ i ];
-+    c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while( ( d = --pos[ c ] ) > i ) {
-+      c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+      long z = t;
-+      t = a[ d ];
-+      a[ d ] = z;
-+      z = u;
-+      u = b[ d ];
-+      b[ d ] = z;
-+     }
-+     a[ i ] = t;
-+     b[ i ] = u;
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, b, i, i + count[ c ] );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays using a parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void parallelRadixSort( final long[] a, final long[] b, final int from, final int to ) {
-+  if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
-+   quickSort( a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch." );
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
-+  queue.add( new Segment( from, to - from, 0 ) );
-+  final AtomicInteger queueSize = new AtomicInteger( 1 );
-+  final int numberOfThreads = Runtime.getRuntime().availableProcessors();
-+  final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
-+  final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
-+  for ( int i = numberOfThreads; i-- != 0; )
-+   executorCompletionService.submit( new Callable<Void>() {
-+    public Void call() throws Exception {
-+     final int[] count = new int[ 1 << DIGIT_BITS ];
-+     final int[] pos = new int[ 1 << DIGIT_BITS ];
-+     for ( ;; ) {
-+      if ( queueSize.get() == 0 ) for ( int i = numberOfThreads; i-- != 0; )
-+       queue.add( POISON_PILL );
-+      final Segment segment = queue.take();
-+      if ( segment == POISON_PILL ) return null;
-+      final int first = segment.offset;
-+      final int length = segment.length;
-+      final int level = segment.level;
-+      final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+      final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+      final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS;
-+      // Count keys.
-+      for ( int i = first + length; i-- != first; )
-+       count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+      // Compute cumulative distribution
-+      int lastUsed = -1;
-+      for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+       if ( count[ i ] != 0 ) lastUsed = i;
-+       pos[ i ] = ( p += count[ i ] );
-+      }
-+      final int end = first + length - count[ lastUsed ];
-+      for ( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+       long t = a[ i ];
-+       long u = b[ i ];
-+       c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+       if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+        while ( ( d = --pos[ c ] ) > i ) {
-+         c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+         final long z = t;
-+         final long w = u;
-+         t = a[ d ];
-+         u = b[ d ];
-+         a[ d ] = z;
-+         b[ d ] = w;
-+        }
-+        a[ i ] = t;
-+        b[ i ] = u;
-+       }
-+       if ( level < maxLevel && count[ c ] > 1 ) {
-+        if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, b, i, i + count[ c ] );
-+        else {
-+         queueSize.incrementAndGet();
-+         queue.add( new Segment( i, count[ c ], level + 1 ) );
-+        }
-+       }
-+      }
-+      queueSize.decrementAndGet();
-+     }
-+    }
-+   } );
-+  Throwable problem = null;
-+  for ( int i = numberOfThreads; i-- != 0; )
-+   try {
-+    executorCompletionService.take().get();
-+   }
-+   catch ( Exception e ) {
-+    problem = e.getCause(); // We keep only the last one. They will be logged anyway.
-+   }
-+  executorService.shutdown();
-+  if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
-+ }
-+ /** Sorts two arrays using a parallel radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
-+	 * in the same position in the two provided arrays will be considered a single key, and permuted
-+	 * accordingly. In the end, either <code>a[ i ] &lt; a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] &le; b[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
-+	 * 
-+	 * @param a the first array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 */
-+ public static void parallelRadixSort( final long[] a, final long[] b ) {
-+  ensureSameLength( a, b );
-+  parallelRadixSort( a, b, 0, a.length );
-+ }
-+ private static void insertionSortIndirect( final int[] perm, final long[] a, final long[] b, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = perm[ i ];
-+   int j = i;
-+   for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ) || ( (a[ t ]) == (a[ u ]) ) && ( (b[ t ]) < (b[ u ]) ); u = perm[ --j - 1 ] ) {
-+    perm[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   perm[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final long[] a, final long[] b, final boolean stable ) {
-+  ensureSameLength( a, b );
-+  radixSortIndirect( perm, a, b, 0, a.length, stable );
-+ }
-+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>a[ perm[ i ] ] &le; a[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
-+	 * version is slightly faster).
-+	 * 
-+	 * @param perm a permutation array indexing <code>a</code>.
-+	 * @param a the array to be sorted.
-+	 * @param b the second array to be sorted.
-+	 * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
-+	 * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
-+	 * @param stable whether the sorting algorithm should be stable.
-+	 */
-+ public static void radixSortIndirect( final int[] perm, final long[] a, final long[] b, final int from, final int to, final boolean stable ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   insertionSortIndirect( perm, a, b, from, to );
-+   return;
-+  }
-+  final int layers = 2;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final int[] support = stable ? new int[ perm.length ] : null;
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ (int)((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   if ( stable ) {
-+    for( int i = first + length; i-- != first; ) support[ --pos[ (int)((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
-+    System.arraycopy( support, 0, perm, first, length );
-+    for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+     if ( level < maxLevel && count[ i ] > 1 ) {
-+      if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, p, p + count[ i ] );
-+      else {
-+       offsetStack[ stackPos ] = p;
-+       lengthStack[ stackPos ] = count[ i ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+     p += count[ i ];
-+    }
-+    java.util.Arrays.fill( count, 0 );
-+   }
-+   else {
-+    final int end = first + length - count[ lastUsed ];
-+    // i moves through the start of each block
-+    for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+     int t = perm[ i ];
-+     c = (int)((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+     if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+      while( ( d = --pos[ c ] ) > i ) {
-+       final int z = t;
-+       t = perm[ d ];
-+       perm[ d ] = z;
-+       c = (int)((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
-+      }
-+      perm[ i ] = t;
-+     }
-+     if ( level < maxLevel && count[ c ] > 1 ) {
-+      if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, i, i + count[ c ] );
-+      else {
-+       offsetStack[ stackPos ] = i;
-+       lengthStack[ stackPos ] = count[ c ];
-+       levelStack[ stackPos++ ] = level + 1;
-+      }
-+     }
-+    }
-+   }
-+  }
-+ }
-+ private static void selectionSort( final long[][] a, final int from, final int to, final int level ) {
-+  final int layers = a.length;
-+  final int firstLayer = level / DIGITS_PER_ELEMENT;
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) {
-+    for( int p = firstLayer; p < layers; p++ ) {
-+     if ( a[ p ][ j ] < a[ p ][ m ] ) {
-+      m = j;
-+      break;
-+     }
-+     else if ( a[ p ][ j ] > a[ p ][ m ] ) break;
-+    }
-+   }
-+   if ( m != i ) {
-+    for( int p = layers; p-- != 0; ) {
-+     final long u = a[ p ][ i ];
-+     a[ p ][ i ] = a[ p ][ m ];
-+     a[ p ][ m ] = u;
-+    }
-+   }
-+  }
-+ }
-+ /** Sorts the specified array of arrays lexicographically using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
-+	 * in the same position will be considered a single key, and permuted
-+	 * accordingly.
-+	 *
-+	 * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
-+	 */
-+ public static void radixSort( final long[][] a ) {
-+  radixSort( a, 0, a[ 0 ].length );
-+ }
-+ /** Sorts the specified array of arrays lexicographically using radix sort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
-+	 * McIlroy, &ldquo;Engineering radix sort&rdquo;, <i>Computing Systems</i>, 6(1), pages 5&minus;27 (1993).
-+	 *
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
-+	 * in the same position will be considered a single key, and permuted
-+	 * accordingly.
-+	 *
-+	 * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static void radixSort( final long[][] a, final int from, final int to ) {
-+  if ( to - from < RADIXSORT_NO_REC ) {
-+   selectionSort( a, from, to, 0 );
-+   return;
-+  }
-+  final int layers = a.length;
-+  final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
-+  for( int p = layers, l = a[ 0 ].length; p-- != 0; ) if ( a[ p ].length != l ) throw new IllegalArgumentException( "The array of index " + p + " has not the same length of the array of index 0." );
-+  final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
-+  int stackPos = 0;
-+  final int[] offsetStack = new int[ stackSize ];
-+  final int[] lengthStack = new int[ stackSize ];
-+  final int[] levelStack = new int[ stackSize ];
-+  offsetStack[ stackPos ] = from;
-+  lengthStack[ stackPos ] = to - from;
-+  levelStack[ stackPos++ ] = 0;
-+  final int[] count = new int[ 1 << DIGIT_BITS ];
-+  final int[] pos = new int[ 1 << DIGIT_BITS ];
-+  final long[] t = new long[ layers ];
-+  while( stackPos > 0 ) {
-+   final int first = offsetStack[ --stackPos ];
-+   final int length = lengthStack[ stackPos ];
-+   final int level = levelStack[ stackPos ];
-+   final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
-+   final long[] k = a[ level / DIGITS_PER_ELEMENT ]; // This is the key array
-+   final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
-+   // Count keys.
-+   for( int i = first + length; i-- != first; ) count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
-+   // Compute cumulative distribution
-+   int lastUsed = -1;
-+   for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
-+    if ( count[ i ] != 0 ) lastUsed = i;
-+    pos[ i ] = ( p += count[ i ] );
-+   }
-+   final int end = first + length - count[ lastUsed ];
-+   // i moves through the start of each block
-+   for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
-+    for( int p = layers; p-- != 0; ) t[ p ] = a[ p ][ i ];
-+    c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
-+    if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
-+     while( ( d = --pos[ c ] ) > i ) {
-+      c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
-+      for( int p = layers; p-- != 0; ) {
-+       final long u = t[ p ];
-+       t[ p ] = a[ p ][ d ];
-+       a[ p ][ d ] = u;
-+      }
-+     }
-+     for( int p = layers; p-- != 0; ) a[ p ][ i ] = t[ p ];
-+    }
-+    if ( level < maxLevel && count[ c ] > 1 ) {
-+     if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, i, i + count[ c ], level + 1 );
-+     else {
-+      offsetStack[ stackPos ] = i;
-+      lengthStack[ stackPos ] = count[ c ];
-+      levelStack[ stackPos++ ] = level + 1;
-+     }
-+    }
-+   }
-+  }
-+ }
-+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param from the index of the first element (inclusive) to be shuffled.
-+	 * @param to the index of the last element (exclusive) to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static long[] shuffle( final long[] a, final int from, final int to, final Random random ) {
-+  for( int i = to - from; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final long t = a[ from + i ];
-+   a[ from + i ] = a[ from + p ];
-+   a[ from + p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Shuffles the specified array using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static long[] shuffle( final long[] a, final Random random ) {
-+  for( int i = a.length; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final long t = a[ i ];
-+   a[ i ] = a[ p ];
-+   a[ p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static long[] reverse( final long[] a ) {
-+  final int length = a.length;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final long t = a[ length - i - 1 ];
-+   a[ length - i - 1 ] = a[ i ];
-+   a[ i ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array fragment.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @param from the index of the first element (inclusive) to be reversed.
-+	 * @param to the index of the last element (exclusive) to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static long[] reverse( final long[] a, final int from, final int to ) {
-+  final int length = to - from;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final long t = a[ from + length - i - 1 ];
-+   a[ from + length - i - 1 ] = a[ from + i ];
-+   a[ from + i ] = t;
-+  }
-+  return a;
-+ }
-+ /** A type-specific content-based hash strategy for arrays. */
-+ private static final class ArrayHashStrategy implements Hash.Strategy<long[]>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  public int hashCode( final long[] o ) {
-+   return java.util.Arrays.hashCode( o );
-+  }
-+  public boolean equals( final long[] a, final long[] b ) {
-+   return java.util.Arrays.equals( a, b );
-+  }
-+ }
-+ /** A type-specific content-based hash strategy for arrays.
-+	 *
-+	 * <P>This hash strategy may be used in custom hash collections whenever keys are
-+	 * arrays, and they must be considered equal by content. This strategy
-+	 * will handle <code>null</code> correctly, and it is serializable.
-+	 */
-+ public final static Hash.Strategy<long[]> HASH_STRATEGY = new ArrayHashStrategy();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.BidirectionalIterator;
-+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
-+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
-+ * and the possibility to skip elements backwards.
-+ *
-+ * @see BidirectionalIterator
-+ */
-+public interface LongBidirectionalIterator extends LongIterator , ObjectBidirectionalIterator<Long> {
-+ /**
-+	 * Returns the previous element as a primitive type.
-+	 *
-+	 * @return the previous element in the iteration.
-+	 * @see java.util.ListIterator#previous()
-+	 */
-+ long previousLong();
-+ /** Moves back for the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #previous()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasPrevious()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip back.
-+	 * @return the number of elements actually skipped.
-+	 * @see java.util.Iterator#next()
-+	 */
-+ int back( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Collection;
-+/** A type-specific {@link Collection}; provides some additional methods
-+ * that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
-+ * a slightly different semantics for {@link #toArray(Object[])}.
-+ *
-+ * @see Collection
-+ */
-+public interface LongCollection extends Collection<Long>, LongIterable {
-+ /** Returns a type-specific iterator on the elements of this collection.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in 
-+	 * {@link java.lang.Iterable#iterator()}, which was already 
-+	 * strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Collection}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this collection.
-+	 */
-+ LongIterator iterator();
-+ /** Returns a type-specific iterator on this elements of this collection.
-+	 *
-+	 * @see #iterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ LongIterator longIterator();
-+ /** Returns an containing the items of this collection;
-+	 * the runtime type of the returned array is that of the specified array. 
-+	 *
-+	 * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ <T> T[] toArray(T[] a);
-+ /**
-+	 * @see Collection#contains(Object)
-+	 */
-+ boolean contains( long key );
-+ /** Returns a primitive type array containing the items of this collection. 
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray()
-+	 */
-+ long[] toLongArray();
-+ /** Returns a primitive type array containing the items of this collection.
-+	 *
-+	 * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ long[] toLongArray( long a[] );
-+ /** Returns a primitive type array containing the items of this collection. 
-+	 *
-+	 * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ long[] toArray( long a[] );
-+ /**
-+	 * @see Collection#add(Object)
-+	 */
-+ boolean add( long key );
-+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
-+	 * with the similarly named index-based method in the {@link java.util.List} interface
-+	 * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
-+	 * <code>remove()</code>.
-+	 *
-+	 * @see Collection#remove(Object)
-+	 */
-+ boolean rem( long key );
-+ /**
-+	 * @see Collection#addAll(Collection)
-+	 */
-+ boolean addAll( LongCollection c );
-+ /**
-+	 * @see Collection#containsAll(Collection)
-+	 */
-+ boolean containsAll( LongCollection c );
-+ /**
-+	 * @see Collection#removeAll(Collection)
-+	 */
-+ boolean removeAll( LongCollection c );
-+ /**
-+	 * @see Collection#retainAll(Collection)
-+	 */
-+ boolean retainAll( LongCollection c );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Collection;
-+import it.unimi.dsi.fastutil.objects.ObjectArrays;
-+/** A class providing static methods and objects that do useful things with type-specific collections.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class LongCollections {
-+ private LongCollections() {}
-+ /** An immutable class representing an empty type-specific collection.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific collection.
-+	 */
-+ public abstract static class EmptyCollection extends AbstractLongCollection {
-+  protected EmptyCollection() {}
-+  public boolean add( long k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( long k ) { return false; }
-+  public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
-+  public long[] toLongArray( long[] a ) { return a; }
-+  public long[] toLongArray() { return LongArrays.EMPTY_ARRAY; }
-+  public boolean rem( long k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( LongCollection c ) { return c.isEmpty(); }
-+ 
-+  public LongBidirectionalIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
-+  public int size() { return 0; }
-+  public void clear() {}
-+  public int hashCode() { return 0; }
-+  public boolean equals( Object o ) {
-+   if ( o == this ) return true;
-+   if ( ! ( o instanceof Collection ) ) return false;
-+   return ((Collection<?>)o).isEmpty();
-+  }
-+ }
-+ /** A synchronized wrapper class for collections. */
-+ public static class SynchronizedCollection implements LongCollection , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongCollection collection;
-+  protected final Object sync;
-+  protected SynchronizedCollection( final LongCollection c, final Object sync ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedCollection( final LongCollection c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = this;
-+  }
-+  public int size() { synchronized( sync ) { return collection.size(); } }
-+  public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
-+  public boolean contains( final long o ) { synchronized( sync ) { return collection.contains( o ); } }
-+  public long[] toLongArray() { synchronized( sync ) { return collection.toLongArray(); } }
-+  public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
-+  public long[] toLongArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
-+  public long[] toArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
-+  public boolean addAll( final LongCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
-+  public boolean containsAll( final LongCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
-+  public boolean removeAll( final LongCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
-+  public boolean retainAll( final LongCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
-+  public boolean add( final Long k ) { synchronized( sync ) { return collection.add( k ); } }
-+  public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
-+  public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
-+  public LongIterator iterator() { return collection.iterator(); }
-+  @Deprecated
-+  public LongIterator longIterator() { return iterator(); }
-+  public boolean add( final long k ) { synchronized( sync ) { return collection.add( k ); } }
-+  public boolean rem( final long k ) { synchronized( sync ) { return collection.rem( k ); } }
-+  public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
-+  public boolean addAll( final Collection<? extends Long> c ) { synchronized( sync ) { return collection.addAll( c ); } }
-+  public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
-+  public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
-+  public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
-+  public void clear() { synchronized( sync ) { collection.clear(); } }
-+  public String toString() { synchronized( sync ) { return collection.toString(); } }
-+ }
-+ /** Returns a synchronized collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static LongCollection synchronize( final LongCollection c ) { return new SynchronizedCollection ( c ); }
-+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @param sync an object that will be used to synchronize the list access.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static LongCollection synchronize( final LongCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
-+ /** An unmodifiable wrapper class for collections. */
-+ public static class UnmodifiableCollection implements LongCollection , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongCollection collection;
-+  protected UnmodifiableCollection( final LongCollection c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+  }
-+  public int size() { return collection.size(); }
-+  public boolean isEmpty() { return collection.isEmpty(); }
-+  public boolean contains( final long o ) { return collection.contains( o ); }
-+  public LongIterator iterator() { return LongIterators.unmodifiable( collection.iterator() ); }
-+  @Deprecated
-+  public LongIterator longIterator() { return iterator(); }
-+  public boolean add( final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return collection.toString(); }
-+  public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
-+  public Object[] toArray() { return collection.toArray(); }
-+  public long[] toLongArray() { return collection.toLongArray(); }
-+  public long[] toLongArray( final long[] a ) { return collection.toLongArray( a ); }
-+  public long[] toArray( final long[] a ) { return collection.toArray( a ); }
-+  public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( final LongCollection c ) { return collection.containsAll( c ); }
-+  public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final Object k ) { return collection.contains( k ); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable view of the specified collection.
-+	 * @see java.util.Collections#unmodifiableCollection(Collection)
-+	 */
-+ public static LongCollection unmodifiable( final LongCollection c ) { return new UnmodifiableCollection ( c ); }
-+ /** A collection wrapper class for iterables. */
-+ public static class IterableCollection extends AbstractLongCollection implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongIterable iterable;
-+  protected IterableCollection( final LongIterable iterable ) {
-+   if ( iterable == null ) throw new NullPointerException();
-+   this.iterable = iterable;
-+  }
-+  public int size() {
-+   int c = 0;
-+   final LongIterator iterator = iterator();
-+   while( iterator.hasNext() ) {
-+    iterator.next();
-+    c++;
-+   }
-+   return c;
-+  }
-+  public boolean isEmpty() { return iterable.iterator().hasNext(); }
-+  public LongIterator iterator() { return iterable.iterator(); }
-+  @Deprecated
-+  public LongIterator longIterator() { return iterator(); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified iterable.
-+	 *
-+	 * @param iterable the iterable object to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable collection view of the specified iterable.
-+	 */
-+ public static LongCollection asCollection( final LongIterable iterable ) {
-+  if ( iterable instanceof LongCollection ) return (LongCollection )iterable;
-+  return new IterableCollection ( iterable );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Comparator;
-+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
-+ * and as primitive types. 
-+ *
-+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
-+ * can be used to implement this interface just by specifying the type-specific
-+ * comparator.
-+ *
-+ * @see Comparator
-+ */
-+public interface LongComparator extends Comparator<Long> {
-+ /** Compares the given primitive types.
-+	 *
-+	 * @see java.util.Comparator
-+	 * @return A positive integer, zero, or a negative integer if the first
-+	 * argument is greater than, equal to, or smaller than, respectively, the
-+	 * second one.
-+	 */
-+ public int compare( long k1, long k2 );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** A class providing static methods and objects that do useful things with comparators.
-+ */
-+public class LongComparators {
-+ private LongComparators() {}
-+ /** A type-specific comparator mimicking the natural order. */
-+ protected static class NaturalImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  public final int compare( final long a, final long b ) {
-+   return ( Long.compare((a),(b)) );
-+  }
-+        private Object readResolve() { return NATURAL_COMPARATOR; }
-+ };
-+
-+ public static final LongComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
-+ /** A type-specific comparator mimicking the opposite of the natural order. */
-+ protected static class OppositeImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  public final int compare( final long a, final long b ) {
-+   return - ( Long.compare((a),(b)) );
-+  }
-+        private Object readResolve() { return OPPOSITE_COMPARATOR; }
-+ };
-+
-+ public static final LongComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
-+ protected static class OppositeComparator extends AbstractLongComparator implements java.io.Serializable {
-+  private static final long serialVersionUID = 1L;
-+  private final LongComparator comparator;
-+  protected OppositeComparator( final LongComparator c ) {
-+   comparator = c;
-+  }
-+  public final int compare( final long a, final long b ) {
-+   return comparator.compare( b, a );
-+  }
-+ };
-+ /** Returns a comparator representing the opposite order of the given comparator. 
-+	 *
-+	 * @param c a comparator.
-+	 * @return a comparator representing the opposite order of <code>c</code>.
-+	 */
-+ public static LongComparator oppositeComparator( final LongComparator c ) {
-+  return new OppositeComparator ( c );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+/** A type-specific {@link Hash} interface.
-+ *
-+ * @see Hash
-+ */
-+public interface LongHash {
-+ /** A type-specific hash strategy.
-+	 *
-+	 * @see it.unimi.dsi.fastutil.Hash.Strategy
-+	 */
-+ public interface Strategy {
-+  /** Returns the hash code of the specified element with respect to this hash strategy.
-+		 *
-+		 * @param e an element.
-+		 * @return the hash code of the given element with respect to this hash strategy.
-+		 */
-+  public int hashCode( long e );
-+  /** Returns true if the given elements are equal with respect to this hash strategy.
-+		 *
-+		 * @param a an element.
-+		 * @param b another element.
-+		 * @return true if the two specified elements are equal with respect to this hash strategy.
-+		 */
-+  public boolean equals( long a, long b );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** A class providing static methods and objects that do useful things with heaps.
-+ *
-+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
-+ * are used in the implementation of heap-based queues, but they may be also used
-+ * directly.
-+ *
-+ */
-+public class LongHeaps {
-+ private LongHeaps() {}
-+ /** Moves the given element down into the heap until it reaches the lowest possible position.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index of the element that must be moved down.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position of the element of index <code>i</code>.
-+	 */
-+
-+ public static int downHeap( final long[] heap, final int size, int i, final LongComparator c ) {
-+  assert i < size;
-+  final long e = heap[ i ];
-+  int child;
-+  if ( c == null )
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    long t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
-+    if ( ( (e) <= (t) ) ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  else
-+   while ( ( child = ( i << 1 ) + 1 ) < size ) {
-+    long t = heap[ child ];
-+    final int right = child + 1;
-+    if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
-+    if ( c.compare( e, t ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = child;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Moves the given element up in the heap until it reaches the highest possible position.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param i the index of the element that must be moved up.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 * @return the new position of the element of index <code>i</code>.
-+	 */
-+
-+ public static int upHeap( final long[] heap, final int size, int i, final LongComparator c ) {
-+  assert i < size;
-+  final long e = heap[ i ];
-+  if ( c == null )
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final long t = heap[ parent ];
-+    if ( ( (t) <= (e) ) ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  else
-+   while ( i != 0 ) {
-+    final int parent = ( i - 1 ) >>> 1;
-+    final long t = heap[ parent ];
-+    if ( c.compare( t, e ) <= 0 ) break;
-+    heap[ i ] = t;
-+    i = parent;
-+   }
-+  heap[ i ] = e;
-+  return i;
-+ }
-+ /** Makes an array into a heap.
-+	 *
-+	 * @param heap the heap (starting at 0).
-+	 * @param size the number of elements in the heap.
-+	 * @param c a type-specific comparator, or <code>null</code> for the natural order.
-+	 */
-+ public static void makeHeap( final long[] heap, final int size, final LongComparator c ) {
-+  int i = size >>> 1;
-+  while( i-- != 0 ) downHeap( heap, size, i, c );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.lang.Iterable;
-+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
-+ *
-+ * <p><strong>Warning</strong>: Java will let you write &ldquo;colon&rdquo; <code>for</code> statements with primitive-type
-+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
-+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
-+ *
-+ * @see Iterable
-+ */
-+public interface LongIterable extends Iterable<Long> {
-+ /** Returns a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
-+	 *
-+	 * @return a type-specific iterator.
-+	 */
-+ LongIterator iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Iterator;
-+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
-+ * the possibility to skip elements.
-+ *
-+ * @see Iterator
-+ */
-+public interface LongIterator extends Iterator<Long> {
-+ /**
-+	 * Returns the next element as a primitive type.
-+	 *
-+	 * @return the next element in the iteration.
-+	 * @see Iterator#next()
-+	 */
-+ long nextLong();
-+ /** Skips the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #next()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasNext()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip.
-+	 * @return the number of elements actually skipped.
-+	 * @see Iterator#next()
-+	 */
-+ int skip( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific iterators.
-+ *
-+ * @see Iterator
-+ */
-+public class LongIterators {
-+ private LongIterators() {}
-+ /** A class returning no elements and a type-specific iterator interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific iterator.
-+	 */
-+ public static class EmptyIterator extends AbstractLongListIterator implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyIterator() {}
-+  public boolean hasNext() { return false; }
-+  public boolean hasPrevious() { return false; }
-+  public long nextLong() { throw new NoSuchElementException(); }
-+  public long previousLong() { throw new NoSuchElementException(); }
-+  public int nextIndex() { return 0; }
-+  public int previousIndex() { return -1; }
-+  public int skip( int n ) { return 0; };
-+  public int back( int n ) { return 0; };
-+  public Object clone() { return EMPTY_ITERATOR; }
-+        private Object readResolve() { return EMPTY_ITERATOR; }
-+ }
-+ /** An empty iterator (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>The class of this objects represent an abstract empty iterator
-+	 * that can iterate as a type-specific (list) iterator.
-+	 */
-+
-+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
-+ /** An iterator returning a single element. */
-+ private static class SingletonIterator extends AbstractLongListIterator {
-+  private final long element;
-+  private int curr;
-+  public SingletonIterator( final long element ) {
-+   this.element = element;
-+  }
-+  public boolean hasNext() { return curr == 0; }
-+  public boolean hasPrevious() { return curr == 1; }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = 1;
-+   return element;
-+  }
-+  public long previousLong() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = 0;
-+   return element;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Returns an iterator that iterates just over the given element.
-+	 *
-+	 * @param element the only element to be returned by a type-specific list iterator.
-+	 * @return  an iterator that iterates just over <code>element</code>.
-+	 */
-+ public static LongListIterator singleton( final long element ) {
-+  return new SingletonIterator ( element );
-+ }
-+ /** A class to wrap arrays in iterators. */
-+ private static class ArrayIterator extends AbstractLongListIterator {
-+  private final long[] array;
-+  private final int offset, length;
-+  private int curr;
-+  public ArrayIterator( final long[] array, final int offset, final int length ) {
-+   this.array = array;
-+   this.offset = offset;
-+   this.length = length;
-+  }
-+  public boolean hasNext() { return curr < length; }
-+  public boolean hasPrevious() { return curr > 0; }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   return array[ offset + curr++ ];
-+  }
-+  public long previousLong() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   return array[ offset + --curr ];
-+  }
-+  public int skip( int n ) {
-+   if ( n <= length - curr ) {
-+    curr += n;
-+    return n;
-+   }
-+   n = length - curr;
-+   curr = length;
-+   return n;
-+  }
-+  public int back( int n ) {
-+   if ( n <= curr ) {
-+    curr -= n;
-+    return n;
-+   }
-+   n = curr;
-+   curr = 0;
-+   return n;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Wraps the given part of an array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will iterate
-+	 * <code>length</code> times, returning consecutive elements of the given
-+	 * array starting from the one with index <code>offset</code>.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param length the number of elements to return.
-+	 * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
-+	 */
-+ public static LongListIterator wrap( final long[] array, final int offset, final int length ) {
-+  LongArrays.ensureOffsetLength( array, offset, length );
-+  return new ArrayIterator ( array, offset, length );
-+ }
-+ /** Wraps the given array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will return
-+	 * all elements of the given array.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @return an iterator that will the elements of <code>array</code>.
-+	 */
-+ public static LongListIterator wrap( final long[] array ) {
-+  return new ArrayIterator ( array, 0, array.length );
-+ }
-+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static int unwrap( final LongIterator i, final long array[], int offset, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextLong();
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given array. The iteration will stop when the
-+	 * iterator has no more elements or when the end of the array has been reached.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static int unwrap( final LongIterator i, final long array[] ) {
-+  return unwrap( i, array, 0, array.length );
-+ }
-+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator. At most <code>max</code> elements
-+	 * will be returned.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be unwrapped.
-+	 * @return an array containing the elements returned by the iterator (at most <code>max</code>).
-+	 */
-+
-+ public static long[] unwrap( final LongIterator i, int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  long array[] = new long[ 16 ];
-+  int j = 0;
-+  while( max-- != 0 && i.hasNext() ) {
-+   if ( j == array.length ) array = LongArrays.grow( array, j + 1 );
-+   array[ j++ ] = i.nextLong();
-+  }
-+  return LongArrays.trim( array, j );
-+ }
-+ /** Unwraps an iterator, returning an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return an array containing the elements returned by the iterator.
-+	 */
-+ public static long[] unwrap( final LongIterator i ) {
-+  return unwrap( i, Integer.MAX_VALUE );
-+ }
-+ /** Unwraps an iterator into a type-specific collection,  with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection array to contain the output of the iterator.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int unwrap( final LongIterator i, final LongCollection c, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) c.add( i.nextLong() );
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given type-specific collection. The returned count on the number
-+	 * unwrapped elements is a long, so that it will work also with very large collections.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection to contain the output of the iterator.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static long unwrap( final LongIterator i, final LongCollection c ) {
-+  long n = 0;
-+  while( i.hasNext() ) {
-+   c.add( i.nextLong() );
-+   n++;
-+  }
-+  return n;
-+ }
-+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection (up to <code>max</code>).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int pour( final LongIterator i, final LongCollection s, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) s.add( i.nextLong() );
-+  return max - j - 1;
-+ }
-+ /** Pours an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static int pour( final LongIterator i, final LongCollection s ) {
-+  return pour( i, s, Integer.MAX_VALUE );
-+ }
-+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return a type-specific list containing the returned elements, up to <code>max</code>.
-+	 */
-+ public static LongList pour( final LongIterator i, int max ) {
-+  final LongArrayList l = new LongArrayList ();
-+  pour( i, l, max );
-+  l.trim();
-+  return l;
-+ }
-+ /** Pours an iterator, returning a type-specific list.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a list containing the returned elements. Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return a type-specific list containing the returned elements.
-+	 */
-+ public static LongList pour( final LongIterator i ) {
-+  return pour( i, Integer.MAX_VALUE );
-+ }
-+ private static class IteratorWrapper extends AbstractLongIterator {
-+  final Iterator<Long> i;
-+  public IteratorWrapper( final Iterator<Long> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public void remove() { i.remove(); }
-+  public long nextLong() { return ((i.next()).longValue()); }
-+ }
-+ /** Wraps a standard iterator into a type-specific iterator.
-+	 *
-+	 * <P>This method wraps a standard iterator into a type-specific one which will handle the
-+	 * type conversions for you. Of course, any attempt to wrap an iterator returning the
-+	 * instances of the wrong class will generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i an iterator.
-+	 * @return a type-specific iterator  backed by <code>i</code>.
-+	 */
-+ @SuppressWarnings({"unchecked","rawtypes"})
-+  public static LongIterator asLongIterator( final Iterator i ) {
-+  if ( i instanceof LongIterator ) return (LongIterator )i;
-+  return new IteratorWrapper ( i );
-+ }
-+ private static class ListIteratorWrapper extends AbstractLongListIterator {
-+  final ListIterator<Long> i;
-+  public ListIteratorWrapper( final ListIterator<Long> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+  public void set( long k ) { i.set( (Long.valueOf(k)) ); }
-+  public void add( long k ) { i.add( (Long.valueOf(k)) ); }
-+  public void remove() { i.remove(); }
-+  public long nextLong() { return ((i.next()).longValue()); }
-+  public long previousLong() { return ((i.previous()).longValue()); }
-+ }
-+ /** Wraps a standard list iterator into a type-specific list iterator.
-+	 *
-+	 * <P>This method wraps a standard list iterator into a type-specific one
-+	 * which will handle the type conversions for you. Of course, any attempt
-+	 * to wrap an iterator returning the instances of the wrong class will
-+	 * generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i a list iterator.
-+	 * @return a type-specific list iterator backed by <code>i</code>.
-+	 */
-+ @SuppressWarnings({"unchecked","rawtypes"})
-+  public static LongListIterator asLongIterator( final ListIterator i ) {
-+  if ( i instanceof LongListIterator ) return (LongListIterator )i;
-+  return new ListIteratorWrapper ( i );
-+ }
-+ private static class IntervalIterator extends AbstractLongBidirectionalIterator {
-+  private final long from, to;
-+  long curr;
-+  public IntervalIterator( final long from, final long to ) {
-+   this.from = this.curr = from;
-+   this.to = to;
-+  }
-+  public boolean hasNext() { return curr < to; }
-+  public boolean hasPrevious() { return curr > from; }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   return curr++;
-+  }
-+  public long previousLong() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   return --curr;
-+  }
-+  public int skip( int n ) {
-+   if ( curr + n <= to ) {
-+    curr += n;
-+    return n;
-+   }
-+   n = (int)( to - curr );
-+   curr = to;
-+   return n;
-+  }
-+  public int back( int n ) {
-+   if ( curr - n >= from ) {
-+    curr -= n;
-+    return n;
-+   }
-+   n = (int)( curr - from );
-+   curr = from;
-+   return n;
-+  }
-+ }
-+ /** Creates a type-specific bidirectional iterator over an interval.
-+	 *
-+	 * <P>The type-specific bidirectional iterator returned by this method will return the
-+	 * elements <code>from</code>, <code>from+1</code>,&hellip;, <code>to-1</code>.
-+	 *
-+	 * <P>Note that all other type-specific interval iterator are <em>list</em>
-+	 * iterators. Of course, this is not possible with longs as the index
-+	 * returned by {@link java.util.ListIterator#nextIndex() nextIndex()}/{@link
-+	 * java.util.ListIterator#previousIndex() previousIndex()} would exceed an integer.
-+	 *
-+	 * @param from the starting element (inclusive).
-+	 * @param to the ending element (exclusive).
-+	 * @return a type-specific bidirectional iterator enumerating the elements from <code>from</code> to <code>to</code>.
-+	 */
-+ public static LongBidirectionalIterator fromTo( final long from, final long to ) {
-+  return new IntervalIterator( from, to );
-+ }
-+ private static class IteratorConcatenator extends AbstractLongIterator {
-+  final LongIterator a[];
-+  int offset, length, lastOffset = -1;
-+  public IteratorConcatenator( final LongIterator a[], int offset, int length ) {
-+   this.a = a;
-+   this.offset = offset;
-+   this.length = length;
-+   advance();
-+  }
-+  private void advance() {
-+   while( length != 0 ) {
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return;
-+  }
-+  public boolean hasNext() {
-+   return length > 0;
-+  }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   long next = a[ lastOffset = offset ].nextLong();
-+   advance();
-+   return next;
-+  }
-+  public void remove() {
-+   if ( lastOffset == -1 ) throw new IllegalStateException();
-+   a[ lastOffset ].remove();
-+  }
-+  public int skip( int n ) {
-+   lastOffset = -1;
-+   int skipped = 0;
-+   while( skipped < n && length != 0 ) {
-+    skipped += a[ offset ].skip( n - skipped );
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return skipped;
-+  }
-+ }
-+ /** Concatenates all iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by all iterators contained in the given array.
-+	 *
-+	 * @param a an array of iterators.
-+	 * @return an iterator obtained by concatenation.
-+	 */
-+ public static LongIterator concat( final LongIterator a[] ) {
-+  return concat( a, 0, a.length );
-+ }
-+ /** Concatenates a sequence of iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by <code>a[ offset ]</code>, then those returned 
-+	 * by <code>a[ offset + 1 ]</code>, and so on up to 
-+	 * <code>a[ offset + length - 1 ]</code>. 
-+	 *
-+	 * @param a an array of iterators.
-+	 * @param offset the index of the first iterator to concatenate.
-+	 * @param length the number of iterators to concatenate.
-+	 * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
-+	 */
-+ public static LongIterator concat( final LongIterator a[], final int offset, final int length ) {
-+  return new IteratorConcatenator ( a, offset, length );
-+ }
-+   /** An unmodifiable wrapper class for iterators. */
-+ public static class UnmodifiableIterator extends AbstractLongIterator {
-+  final protected LongIterator i;
-+  public UnmodifiableIterator( final LongIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public long nextLong() { return i.nextLong(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Long next() { return i.next(); }
-+ }
-+ /** Returns an unmodifiable iterator backed by the specified iterator.
-+	 *
-+	 * @param i the iterator to be wrapped in an unmodifiable iterator.
-+	 * @return an unmodifiable view of the specified iterator.
-+	 */
-+ public static LongIterator unmodifiable( final LongIterator i ) { return new UnmodifiableIterator ( i ); }
-+   /** An unmodifiable wrapper class for bidirectional iterators. */
-+ public static class UnmodifiableBidirectionalIterator extends AbstractLongBidirectionalIterator {
-+  final protected LongBidirectionalIterator i;
-+  public UnmodifiableBidirectionalIterator( final LongBidirectionalIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public long nextLong() { return i.nextLong(); }
-+  public long previousLong() { return i.previousLong(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Long next() { return i.next(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Long previous() { return i.previous(); }
-+ }
-+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
-+	 *
-+	 * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
-+	 * @return an unmodifiable view of the specified bidirectional iterator.
-+	 */
-+ public static LongBidirectionalIterator unmodifiable( final LongBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
-+   /** An unmodifiable wrapper class for list iterators. */
-+ public static class UnmodifiableListIterator extends AbstractLongListIterator {
-+  final protected LongListIterator i;
-+  public UnmodifiableListIterator( final LongListIterator i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public long nextLong() { return i.nextLong(); }
-+  public long previousLong() { return i.previousLong(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Long next() { return i.next(); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  @Override
-+  public Long previous() { return i.previous(); }
-+ }
-+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
-+	 *
-+	 * @param i the list iterator to be wrapped in an unmodifiable list iterator.
-+	 * @return an unmodifiable view of the specified list iterator.
-+	 */
-+ public static LongListIterator unmodifiable( final LongListIterator i ) { return new UnmodifiableListIterator ( i ); }
-+
-+    /** A wrapper promoting the results of an IntIterator. */
-+ protected static class IntIteratorWrapper implements LongIterator {
-+  final it.unimi.dsi.fastutil.ints.IntIterator iterator;
-+  public IntIteratorWrapper( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
-+   this.iterator = iterator;
-+  }
-+  public boolean hasNext() { return iterator.hasNext(); }
-+  public Long next() { return Long.valueOf( iterator.nextInt() ); }
-+  public long nextLong() { return iterator.nextInt(); }
-+  public void remove() { iterator.remove(); }
-+  public int skip( final int n ) { return iterator.skip( n ); }
-+ }
-+ /** Returns an iterator backed by the specified integer iterator. 
-+	 * @return an iterator backed by the specified integer iterator. 
-+	 */
-+ public static LongIterator wrap( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
-+  return new IntIteratorWrapper( iterator );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.List;
-+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
-+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
-+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #listIterator()},
-+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
-+ *
-+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
-+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
-+ * of these methods, it is expected that concrete implementation override them with optimized versions.
-+ *
-+ * @see List
-+ */
-+public interface LongList extends List<Long>, Comparable<List<? extends Long>>, LongCollection {
-+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
-+	 *
-+	 * Note that this specification strengthens the one given in {@link List#iterator()}.
-+	 * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
-+	 * in {@link List}.
-+	 *
-+	 * @return an iterator on the elements of this list (in proper sequence).
-+	 */
-+ LongListIterator iterator();
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see #listIterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
-+	 */
-+ @Deprecated
-+ LongListIterator longListIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see #listIterator(int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
-+	 */
-+ @Deprecated
-+ LongListIterator longListIterator( int index );
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see List#listIterator()
-+	 */
-+ LongListIterator listIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see List#listIterator(int)
-+	 */
-+ LongListIterator listIterator( int index );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 * @see List#subList(int,int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
-+	 */
-+ @Deprecated
-+ LongList longSubList( int from, int to );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
-+	 *
-+	 * @see List#subList(int,int)
-+	 */
-+ LongList subList(int from, int to);
-+ /** Sets the size of this list.
-+	 *
-+	 * <P>If the specified size is smaller than the current size, the last elements are
-+	 * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
-+	 *
-+	 * @param size the new size.
-+	 */
-+ void size( int size );
-+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ void getElements( int from, long a[], int offset, int length );
-+ /** Removes (hopefully quickly) elements of this type-specific list.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ void removeElements( int from, int to );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 */
-+ void addElements( int index, long a[] );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ void addElements( int index, long a[], int offset, int length );
-+ /**
-+	 * @see List#add(Object)
-+	 */
-+ boolean add( long key );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ void add( int index, long key );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( int index, LongCollection c );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( int index, LongList c );
-+ /**
-+	 * @see List#add(int,Object)
-+	 */
-+ boolean addAll( LongList c );
-+ /**
-+	 * @see List#get(int)
-+	 */
-+ long getLong( int index );
-+ /**
-+	 * @see List#indexOf(Object)
-+	 */
-+ int indexOf( long k );
-+ /**
-+	 * @see List#lastIndexOf(Object)
-+	 */
-+ int lastIndexOf( long k );
-+ /**
-+	 * @see List#remove(int)
-+	 */
-+ long removeLong( int index );
-+ /**
-+	 * @see List#set(int,Object)
-+	 */
-+ long set( int index, long k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.ListIterator;
-+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
-+ *
-+ * <P>This interface merges the methods provided by a {@link ListIterator} and
-+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
-+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
-+ * and {@link java.util.ListIterator#set(Object) set()}.
-+ *
-+ * @see java.util.ListIterator
-+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
-+ */
-+public interface LongListIterator extends ListIterator<Long>, LongBidirectionalIterator {
-+ void set( long k );
-+ void add( long k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.List;
-+import java.util.Collection;
-+import java.util.Random;
-+/** A class providing static methods and objects that do useful things with type-specific lists.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class LongLists {
-+ private LongLists() {}
-+ /** Shuffles the specified list using the specified pseudorandom number generator.
-+	 * 
-+	 * @param l the list to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>l</code>.
-+	 */
-+ public static LongList shuffle( final LongList l, final Random random ) {
-+  for( int i = l.size(); i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final long t = l.getLong( i );
-+   l.set( i, l.getLong( p ) );
-+   l.set( p, t );
-+  }
-+  return l;
-+ }
-+ /** An immutable class representing an empty type-specific list.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific list.
-+	 */
-+ public static class EmptyList extends LongCollections.EmptyCollection implements LongList , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyList() {}
-+  public void add( final int index, final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final long k ) { throw new UnsupportedOperationException(); }
-+  public long removeLong( int i ) { throw new UnsupportedOperationException(); }
-+  public long set( final int index, final long k ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( long k ) { return -1; }
-+  public int lastIndexOf( long k ) { return -1; }
-+  public boolean addAll( Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public Long get( int i ) { throw new IndexOutOfBoundsException(); }
-+  public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( LongList c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( int i, LongList c ) { throw new UnsupportedOperationException(); }
-+  public void add( final int index, final Long k ) { throw new UnsupportedOperationException(); }
-+  public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
-+  public Long set( final int index, final Long k ) { throw new UnsupportedOperationException(); }
-+  public long getLong( int i ) { throw new IndexOutOfBoundsException(); }
-+  public Long remove( int k ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( Object k ) { return -1; }
-+  public int lastIndexOf( Object k ) { return -1; }
-+  //SUPPRESS_WARNINGS_KEY_UNCHECKED
-+  //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
-+  @Deprecated
-+ 
-+  public LongIterator longIterator() { return LongIterators.EMPTY_ITERATOR; }
-+ 
-+  public LongListIterator listIterator() { return LongIterators.EMPTY_ITERATOR; }
-+ 
-+  public LongListIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
-+ 
-+  public LongListIterator listIterator( int i ) { if ( i == 0 ) return LongIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
-+  @Deprecated
-+  public LongListIterator longListIterator() { return listIterator(); }
-+  @Deprecated
-+  public LongListIterator longListIterator( int i ) { return listIterator( i ); }
-+  public LongList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
-+  @Deprecated
-+  public LongList longSubList( int from, int to ) { return subList( from, to ); }
-+  public void getElements( int from, long[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
-+  public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
-+  public void size( int s ) { throw new UnsupportedOperationException(); }
-+  public int compareTo( final List<? extends Long> o ) {
-+   if ( o == this ) return 0;
-+   return ((List<?>)o).isEmpty() ? 0 : -1;
-+  }
-+  private Object readResolve() { return EMPTY_LIST; }
-+  public Object clone() { return EMPTY_LIST; }
-+  public int hashCode() { return 1; }
-+  @SuppressWarnings("rawtypes")
-+  public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
-+  public String toString() { return "[]"; }
-+ }
-+ /** An empty list (immutable). It is serializable and cloneable. 
-+	 */
-+
-+ public static final EmptyList EMPTY_LIST = new EmptyList();
-+ /** An immutable class representing a type-specific singleton list. 
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific list.
-+	 */
-+ public static class Singleton extends AbstractLongList implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  private final long element;
-+  private Singleton( final long element ) {
-+   this.element = element;
-+  }
-+  public long getLong( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
-+  public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final long k ) { return ( (k) == (element) ); }
-+  public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int i, final Collection <? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
-+  public long[] toLongArray() {
-+   long a[] = new long[ 1 ];
-+   a[ 0 ] = element;
-+   return a;
-+  }
-+  public LongListIterator listIterator() { return LongIterators.singleton( element ); }
-+  public LongListIterator iterator() { return listIterator(); }
-+  public LongListIterator listIterator( int i ) {
-+   if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
-+   LongListIterator l = listIterator();
-+   if ( i == 1 ) l.next();
-+   return l;
-+  }
-+ 
-+  public LongList subList( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+   if ( from != 0 || to != 1 ) return EMPTY_LIST;
-+   return this;
-+  }
-+  public int size() { return 1; }
-+  public void size( final int size ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public Object clone() { return this; }
-+  public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int i, final LongCollection c ) { throw new UnsupportedOperationException(); }
-+ }
-+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned list.
-+	 * @return a type-specific immutable list containing just <code>element</code>.
-+	 */
-+ public static LongList singleton( final long element ) { return new Singleton ( element ); }
-+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned list.
-+	 * @return a type-specific immutable list containing just <code>element</code>.
-+	 */
-+ public static LongList singleton( final Object element ) { return new Singleton ( ((((Long)(element)).longValue())) ); }
-+ /** A synchronized wrapper class for lists. */
-+ public static class SynchronizedList extends LongCollections.SynchronizedCollection implements LongList , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
-+  protected SynchronizedList( final LongList l, final Object sync ) {
-+   super( l, sync );
-+   this.list = l;
-+  }
-+  protected SynchronizedList( final LongList l ) {
-+   super( l );
-+   this.list = l;
-+  }
-+  public long getLong( final int i ) { synchronized( sync ) { return list.getLong( i ); } }
-+  public long set( final int i, final long k ) { synchronized( sync ) { return list.set( i, k ); } }
-+  public void add( final int i, final long k ) { synchronized( sync ) { list.add( i, k ); } }
-+  public long removeLong( final int i ) { synchronized( sync ) { return list.removeLong( i ); } }
-+  public int indexOf( final long k ) { synchronized( sync ) { return list.indexOf( k ); } }
-+  public int lastIndexOf( final long k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
-+  public boolean addAll( final int index, final Collection<? extends Long> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
-+  public void getElements( final int from, final long a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
-+  public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
-+  public void addElements( int index, final long a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
-+  public void addElements( int index, final long a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
-+  public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
-+  public LongListIterator iterator() { return list.listIterator(); }
-+  public LongListIterator listIterator() { return list.listIterator(); }
-+  public LongListIterator listIterator( final int i ) { return list.listIterator( i ); }
-+  @Deprecated
-+  public LongListIterator longListIterator() { return listIterator(); }
-+  @Deprecated
-+  public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
-+  public LongList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
-+  @Deprecated
-+  public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
-+  public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
-+  public int compareTo( final List<? extends Long> o ) { synchronized( sync ) { return list.compareTo( o ); } }
-+  public boolean addAll( final int index, final LongCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
-+  public boolean addAll( final int index, LongList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
-+  public boolean addAll( LongList l ) { synchronized( sync ) { return list.addAll( l ); } }
-+  public Long get( final int i ) { synchronized( sync ) { return list.get( i ); } }
-+  public void add( final int i, Long k ) { synchronized( sync ) { list.add( i, k ); } }
-+  public Long set( final int index, Long k ) { synchronized( sync ) { return list.set( index, k ); } }
-+  public Long remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
-+  public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
-+  public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
-+ }
-+ /** Returns a synchronized type-specific list backed by the given type-specific list.
-+	 *
-+	 * @param l the list to be wrapped in a synchronized list.
-+	 * @return a synchronized view of the specified list.
-+	 * @see java.util.Collections#synchronizedList(List)
-+	 */
-+ public static LongList synchronize( final LongList l ) { return new SynchronizedList ( l ); }
-+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
-+	 *
-+	 * @param l the list to be wrapped in a synchronized list.
-+	 * @param sync an object that will be used to synchronize the access to the list.
-+	 * @return a synchronized view of the specified list.
-+	 * @see java.util.Collections#synchronizedList(List)
-+	 */
-+ public static LongList synchronize( final LongList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
-+ /** An unmodifiable wrapper class for lists. */
-+ public static class UnmodifiableList extends LongCollections.UnmodifiableCollection implements LongList , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
-+  protected UnmodifiableList( final LongList l ) {
-+   super( l );
-+   this.list = l;
-+  }
-+  public long getLong( final int i ) { return list.getLong( i ); }
-+  public long set( final int i, final long k ) { throw new UnsupportedOperationException(); }
-+  public void add( final int i, final long k ) { throw new UnsupportedOperationException(); }
-+  public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( final long k ) { return list.indexOf( k ); }
-+  public int lastIndexOf( final long k ) { return list.lastIndexOf( k ); }
-+  public boolean addAll( final int index, final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public void getElements( final int from, final long a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
-+  public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
-+  public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
-+  public void size( final int size ) { list.size( size ); }
-+  public LongListIterator iterator() { return listIterator(); }
-+  public LongListIterator listIterator() { return LongIterators.unmodifiable( list.listIterator() ); }
-+  public LongListIterator listIterator( final int i ) { return LongIterators.unmodifiable( list.listIterator( i ) ); }
-+  @Deprecated
-+  public LongListIterator longListIterator() { return listIterator(); }
-+  @Deprecated
-+  public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
-+  public LongList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
-+  @Deprecated
-+  public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
-+  public boolean equals( final Object o ) { return collection.equals( o ); }
-+  public int hashCode() { return collection.hashCode(); }
-+  public int compareTo( final List<? extends Long> o ) { return list.compareTo( o ); }
-+  public boolean addAll( final int index, final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final LongList l ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final int index, final LongList l ) { throw new UnsupportedOperationException(); }
-+  public Long get( final int i ) { return list.get( i ); }
-+  public void add( final int i, Long k ) { throw new UnsupportedOperationException(); }
-+  public Long set( final int index, Long k ) { throw new UnsupportedOperationException(); }
-+  public Long remove( final int i ) { throw new UnsupportedOperationException(); }
-+  public int indexOf( final Object o ) { return list.indexOf( o ); }
-+  public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
-+ }
-+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
-+	 *
-+	 * @param l the list to be wrapped in an unmodifiable list.
-+	 * @return an unmodifiable view of the specified list.
-+	 * @see java.util.Collections#unmodifiableList(List)
-+	 */
-+ public static LongList unmodifiable( final LongList l ) { return new UnmodifiableList ( l ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.NoSuchElementException;
-+/** A type-specific hash set with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
-+ * is specified at creation time.
-+ *
-+ * <P>Instances of this class use a hash table to represent a set. The table is
-+ * filled up to a specified <em>load factor</em>, and then doubled in size to
-+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
-+ * of the load factor, it is halved in size. However, halving is
-+ * not performed when deleting entries from an iterator, as it would interfere
-+ * with the iteration process.
-+ *
-+ * <p>Note that {@link #clear()} does not modify the hash table size. 
-+ * Rather, a family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class LongOpenCustomHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient long[] key;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the null key. */
-+ protected transient boolean containsNull;
-+ /** The hash strategy of this custom set. */
-+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
-+ /** The current table size. Note that an additional element is allocated for storing the null key. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the null key, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Creates a new hash set.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+
-+ public LongOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this.strategy = strategy;
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( expected, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+ this( c.size(), f, strategy );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( c, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final LongCollection c, final float f, it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+ this( c.size(), f, strategy );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final LongCollection c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( c, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final LongIterator i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( DEFAULT_INITIAL_SIZE, f, strategy );
-+  while( i.hasNext() ) add( i.nextLong() );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final LongIterator i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( i, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( LongIterators.asLongIterator( i ), f, strategy );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( LongIterators.asLongIterator( i ), strategy );
-+ }
-+ /** Creates a new hash set and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+ this( length < 0 ? 0 : length, f, strategy );
-+  LongArrays.ensureOffsetLength( a, offset, length );
-+  for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Creates a new hash set copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final long[] a, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( a, 0, a.length, f, strategy );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param strategy the strategy.
-+	 */
-+ public LongOpenCustomHashSet( final long[] a, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
-+  this( a, DEFAULT_LOAD_FACTOR, strategy );
-+ }
-+ /** Returns the hashing strategy.
-+	 *
-+	 * @return the hashing strategy of this custom hash set.
-+	 */
-+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
-+  return strategy;
-+ }
-+ private int realSize() {
-+  return containsNull ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( LongCollection c ) {
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( Collection<? extends Long> c ) {
-+  // The resulting collection will be at least c.size() big
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ public boolean add( final long k ) {
-+  int pos;
-+  if ( ( strategy.equals( (k), (0) ) ) ) {
-+   if ( containsNull ) return false;
-+   containsNull = true;
-+   key[ n ] = k;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
-+    if ( ( strategy.equals( (curr), (k) ) ) ) return false;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( strategy.equals( (curr), (k) ) ) ) return false;
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  long curr;
-+  final long[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     return;
-+    }
-+    slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+  }
-+ }
-+ private boolean removeEntry( final int pos ) {
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+ private boolean removeNullEntry() {
-+  containsNull = false;
-+  key[ n ] = (0);
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+
-+ public boolean remove( final long k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) {
-+   if ( containsNull ) return removeNullEntry();
-+   return false;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
-+  }
-+ }
-+
-+ public boolean contains( final long k ) {
-+  if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
-+  if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( strategy.equals( (k), (curr) ) ) ) return true;
-+  }
-+ }
-+ /* Removes all elements from this set.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNull = false;
-+  Arrays.fill( key, (0) );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** An iterator over a hash set. */
-+ private class SetIterator extends AbstractLongIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the null key. */
-+  boolean mustReturnNull = LongOpenCustomHashSet.this.containsNull;
-+  /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
-+  LongArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNull ) {
-+    mustReturnNull = false;
-+    last = n;
-+    return key[ n ];
-+   }
-+   final long key[] = LongOpenCustomHashSet.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     return wrapped.getLong( - pos - 1 );
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   long curr;
-+   final long[] key = LongOpenCustomHashSet.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      return;
-+     }
-+     slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    LongOpenCustomHashSet.this.containsNull = false;
-+    LongOpenCustomHashSet.this.key[ n ] = (0);
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    LongOpenCustomHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+ }
-+ public LongIterator iterator() {
-+  return new SetIterator();
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes this set, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing.
-+	 *
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this set if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this set in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing sets.  {@linkplain #clear() Clearing a
-+	 * set} leaves the table size untouched. If you are reusing a set
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient sets.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the set.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+
-+ protected void rehash( final int newN ) {
-+  final long key[] = this.key;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final long newKey[] = new long[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+  }
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public LongOpenCustomHashSet clone() {
-+  LongOpenCustomHashSet c;
-+  try {
-+   c = (LongOpenCustomHashSet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.containsNull = containsNull;
-+  c.strategy = strategy;
-+  return c;
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    h += ( strategy.hashCode(key[ i ]) );
-+   i++;
-+  }
-+  // Zero / null have hash zero.		
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final LongIterator i = iterator();
-+  s.defaultWriteObject();
-+  for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final long key[] = this.key = new long[ n + 1 ];
-+  long k;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readLong();
-+   if ( ( strategy.equals( (k), (0) ) ) ) {
-+    pos = n;
-+    containsNull = true;
-+   }
-+   else {
-+    if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
-+     while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Hash;
-+import it.unimi.dsi.fastutil.HashCommon;
-+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
-+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.NoSuchElementException;
-+/**  A type-specific hash set with with a fast, small-footprint implementation.
-+ *
-+ * <P>Instances of this class use a hash table to represent a set. The table is
-+ * enlarged as needed by doubling its size when new entries are created, but it is <em>never</em> made
-+ * smaller (even on a {@link #clear()}). A family of {@linkplain #trim() trimming
-+ * methods} lets you control the size of the table; this is particularly useful
-+ * if you reuse instances of this class.
-+ *
-+ * @see Hash
-+ * @see HashCommon
-+ */
-+public class LongOpenHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
-+    private static final long serialVersionUID = 0L;
-+ private static final boolean ASSERTS = false;
-+ /** The array of keys. */
-+ protected transient long[] key;
-+ /** The mask for wrapping a position counter. */
-+ protected transient int mask;
-+ /** Whether this set contains the null key. */
-+ protected transient boolean containsNull;
-+ /** The current table size. Note that an additional element is allocated for storing the null key. */
-+ protected transient int n;
-+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
-+ protected transient int maxFill;
-+ /** Number of entries in the set (including the null key, if present). */
-+ protected int size;
-+ /** The acceptable load factor. */
-+ protected final float f;
-+ /** Creates a new hash set.
-+	 *
-+	 * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 * @param f the load factor.
-+	 */
-+
-+ public LongOpenHashSet( final int expected, final float f ) {
-+  if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
-+  if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
-+  this.f = f;
-+  n = arraySize( expected, f );
-+  mask = n - 1;
-+  maxFill = maxFill( n, f );
-+  key = new long[ n + 1 ];
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 *
-+	 * @param expected the expected number of elements in the hash set. 
-+	 */
-+ public LongOpenHashSet( final int expected ) {
-+  this( expected, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
-+	 * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
-+	 */
-+ public LongOpenHashSet() {
-+  this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final Collection<? extends Long> c, final float f ) {
-+  this( c.size(), f );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given collection.
-+	 *
-+	 * @param c a {@link Collection} to be copied into the new hash set. 
-+	 */
-+ public LongOpenHashSet( final Collection<? extends Long> c ) {
-+  this( c, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final LongCollection c, final float f ) {
-+  this( c.size(), f );
-+  addAll( c );
-+ }
-+ /** Creates a new hash set  with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection to be copied into the new hash set. 
-+	 */
-+ public LongOpenHashSet( final LongCollection c ) {
-+  this( c, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final LongIterator i, final float f ) {
-+  this( DEFAULT_INITIAL_SIZE, f );
-+  while( i.hasNext() ) add( i.nextLong() );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
-+	 *
-+	 * @param i a type-specific iterator whose elements will fill the set.
-+	 */
-+ public LongOpenHashSet( final LongIterator i ) {
-+  this( i, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final Iterator<?> i, final float f ) {
-+  this( LongIterators.asLongIterator( i ), f );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
-+	 *
-+	 * @param i an iterator whose elements will fill the set.
-+	 */
-+ public LongOpenHashSet( final Iterator<?> i ) {
-+  this( LongIterators.asLongIterator( i ) );
-+ }
-+ /** Creates a new hash set and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final long[] a, final int offset, final int length, final float f ) {
-+  this( length < 0 ? 0 : length, f );
-+  LongArrays.ensureOffsetLength( a, offset, length );
-+  for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the set.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 */
-+ public LongOpenHashSet( final long[] a, final int offset, final int length ) {
-+  this( a, offset, length, DEFAULT_LOAD_FACTOR );
-+ }
-+ /** Creates a new hash set copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 * @param f the load factor.
-+	 */
-+ public LongOpenHashSet( final long[] a, final float f ) {
-+  this( a, 0, a.length, f );
-+ }
-+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor 
-+	 * copying the elements of an array.
-+	 *
-+	 * @param a an array to be copied into the new hash set. 
-+	 */
-+ public LongOpenHashSet( final long[] a ) {
-+  this( a, DEFAULT_LOAD_FACTOR );
-+ }
-+ private int realSize() {
-+  return containsNull ? size - 1 : size;
-+ }
-+ private void ensureCapacity( final int capacity ) {
-+  final int needed = arraySize( capacity, f );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ private void tryCapacity( final long capacity ) {
-+  final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
-+  if ( needed > n ) rehash( needed );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( LongCollection c ) {
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ /** {@inheritDoc} */
-+ public boolean addAll( Collection<? extends Long> c ) {
-+  // The resulting collection will be at least c.size() big
-+  if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
-+  else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
-+  return super.addAll( c );
-+ }
-+ public boolean add( final long k ) {
-+  int pos;
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) return false;
-+   containsNull = true;
-+  }
-+  else {
-+   long curr;
-+   final long[] key = this.key;
-+   // The starting point.
-+   if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
-+    if ( ( (curr) == (k) ) ) return false;
-+    while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
-+     if ( ( (curr) == (k) ) ) return false;
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
-+  if ( ASSERTS ) checkTable();
-+  return true;
-+ }
-+ /** Shifts left entries with the specified hash code, starting at the specified position,
-+	 * and empties the resulting free entry.
-+	 *
-+	 * @param pos a starting position.
-+	 */
-+ protected final void shiftKeys( int pos ) {
-+  // Shift entries with the same hash.
-+  int last, slot;
-+  long curr;
-+  final long[] key = this.key;
-+  for(;;) {
-+   pos = ( ( last = pos ) + 1 ) & mask;
-+   for(;;) {
-+    if ( ( (curr = key[ pos ]) == (0) ) ) {
-+     key[ last ] = (0);
-+     return;
-+    }
-+    slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+    if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+    pos = ( pos + 1 ) & mask;
-+   }
-+   key[ last ] = curr;
-+  }
-+ }
-+ private boolean removeEntry( final int pos ) {
-+  size--;
-+  shiftKeys( pos );
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+ private boolean removeNullEntry() {
-+  containsNull = false;
-+  key[ n ] = (0);
-+  size--;
-+  if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
-+  return true;
-+ }
-+
-+ public boolean remove( final long k ) {
-+  if ( ( (k) == (0) ) ) {
-+   if ( containsNull ) return removeNullEntry();
-+   return false;
-+  }
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return removeEntry( pos );
-+  }
-+ }
-+
-+ public boolean contains( final long k ) {
-+  if ( ( (k) == (0) ) ) return containsNull;
-+  long curr;
-+  final long[] key = this.key;
-+  int pos;
-+  // The starting point.
-+  if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
-+  if ( ( (k) == (curr) ) ) return true;
-+  while( true ) {
-+   if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
-+   if ( ( (k) == (curr) ) ) return true;
-+  }
-+ }
-+ /* Removes all elements from this set.
-+	 *
-+	 * <P>To increase object reuse, this method does not change the table size.
-+	 * If you want to reduce the table size, you must use {@link #trim()}.
-+	 *
-+	 */
-+ public void clear() {
-+  if ( size == 0 ) return;
-+  size = 0;
-+  containsNull = false;
-+  Arrays.fill( key, (0) );
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** A no-op for backward compatibility.
-+	 * 
-+	 * @param growthFactor unused.
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public void growthFactor( int growthFactor ) {}
-+ /** Gets the growth factor (2).
-+	 *
-+	 * @return the growth factor of this set, which is fixed (2).
-+	 * @see #growthFactor(int)
-+	 * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
-+	 */
-+ @Deprecated
-+ public int growthFactor() {
-+  return 16;
-+ }
-+ /** An iterator over a hash set. */
-+ private class SetIterator extends AbstractLongIterator {
-+  /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
-+			element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
-+  int pos = n;
-+  /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
-+			or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
-+			we did not return an entry yet, or the last returned entry has been removed. */
-+  int last = -1;
-+  /** A downward counter measuring how many entries must still be returned. */
-+  int c = size;
-+  /** A boolean telling us whether we should return the null key. */
-+  boolean mustReturnNull = LongOpenHashSet.this.containsNull;
-+  /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
-+  LongArrayList wrapped;
-+  public boolean hasNext() {
-+   return c != 0;
-+  }
-+  public long nextLong() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   c--;
-+   if ( mustReturnNull ) {
-+    mustReturnNull = false;
-+    last = n;
-+    return key[ n ];
-+   }
-+   final long key[] = LongOpenHashSet.this.key;
-+   for(;;) {
-+    if ( --pos < 0 ) {
-+     // We are just enumerating elements from the wrapped list.
-+     last = Integer.MIN_VALUE;
-+     return wrapped.getLong( - pos - 1 );
-+    }
-+    if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
-+   }
-+  }
-+  /** Shifts left entries with the specified hash code, starting at the specified position,
-+		 * and empties the resulting free entry.
-+		 *
-+		 * @param pos a starting position.
-+		 */
-+  private final void shiftKeys( int pos ) {
-+   // Shift entries with the same hash.
-+   int last, slot;
-+   long curr;
-+   final long[] key = LongOpenHashSet.this.key;
-+   for(;;) {
-+    pos = ( ( last = pos ) + 1 ) & mask;
-+    for(;;) {
-+     if ( ( (curr = key[ pos ]) == (0) ) ) {
-+      key[ last ] = (0);
-+      return;
-+     }
-+     slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
-+     if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
-+     pos = ( pos + 1 ) & mask;
-+    }
-+    if ( pos < last ) { // Wrapped entry.
-+     if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
-+     wrapped.add( key[ pos ] );
-+    }
-+    key[ last ] = curr;
-+   }
-+  }
-+  public void remove() {
-+   if ( last == -1 ) throw new IllegalStateException();
-+   if ( last == n ) {
-+    LongOpenHashSet.this.containsNull = false;
-+    LongOpenHashSet.this.key[ n ] = (0);
-+   }
-+   else if ( pos >= 0 ) shiftKeys( last );
-+   else {
-+    // We're removing wrapped entries.
-+    LongOpenHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
-+    last = -1; // Note that we must not decrement size
-+    return;
-+   }
-+   size--;
-+   last = -1; // You can no longer remove this entry.
-+   if ( ASSERTS ) checkTable();
-+  }
-+ }
-+ public LongIterator iterator() {
-+  return new SetIterator();
-+ }
-+ /** A no-op for backward compatibility. The kind of tables implemented by
-+	 * this class never need rehashing.
-+	 *
-+	 * <P>If you need to reduce the table size to fit exactly
-+	 * this set, use {@link #trim()}.
-+	 *
-+	 * @return true.
-+	 * @see #trim()
-+	 * @deprecated A no-op.
-+	 */
-+ @Deprecated
-+ public boolean rehash() {
-+  return true;
-+ }
-+ /** Rehashes this set, making the table as small as possible.
-+	 * 
-+	 * <P>This method rehashes the table to the smallest size satisfying the
-+	 * load factor. It can be used when the set will not be changed anymore, so
-+	 * to optimize access speed and size.
-+	 *
-+	 * <P>If the table size is already the minimum possible, this method
-+	 * does nothing.
-+	 *
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim(int)
-+	 */
-+ public boolean trim() {
-+  final int l = arraySize( size, f );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch(OutOfMemoryError cantDoIt) { return false; }
-+  return true;
-+ }
-+ /** Rehashes this set if the table is too large.
-+	 * 
-+	 * <P>Let <var>N</var> be the smallest table size that can hold
-+	 * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
-+	 * table size is smaller than or equal to <var>N</var>, this method does
-+	 * nothing. Otherwise, it rehashes this set in a table of size
-+	 * <var>N</var>.
-+	 *
-+	 * <P>This method is useful when reusing sets.  {@linkplain #clear() Clearing a
-+	 * set} leaves the table size untouched. If you are reusing a set
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large table just
-+	 * because of a few large transient sets.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 * @return true if there was enough memory to trim the set.
-+	 * @see #trim()
-+	 */
-+ public boolean trim( final int n ) {
-+  final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
-+  if ( l >= n || size > maxFill( l, f ) ) return true;
-+  try {
-+   rehash( l );
-+  }
-+  catch( OutOfMemoryError cantDoIt ) { return false; }
-+  return true;
-+ }
-+ /** Rehashes the set.
-+	 *
-+	 * <P>This method implements the basic rehashing strategy, and may be
-+	 * overriden by subclasses implementing different rehashing strategies (e.g.,
-+	 * disk-based rehashing). However, you should not override this method
-+	 * unless you understand the internal workings of this class.
-+	 *
-+	 * @param newN the new size
-+	 */
-+
-+ protected void rehash( final int newN ) {
-+  final long key[] = this.key;
-+  final int mask = newN - 1; // Note that this is used by the hashing macro
-+  final long newKey[] = new long[ newN + 1 ];
-+  int i = n, pos;
-+  for( int j = realSize(); j-- != 0; ) {
-+   while( ( (key[ --i ]) == (0) ) );
-+   if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
-+    while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   newKey[ pos ] = key[ i ];
-+  }
-+  n = newN;
-+  this.mask = mask;
-+  maxFill = maxFill( n, f );
-+  this.key = newKey;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+
-+ public LongOpenHashSet clone() {
-+  LongOpenHashSet c;
-+  try {
-+   c = (LongOpenHashSet )super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.key = key.clone();
-+  c.containsNull = containsNull;
-+  return c;
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * This method overrides the generic method provided by the superclass. 
-+	 * Since <code>equals()</code> is not overriden, it is important
-+	 * that the value returned by this method is the same value as
-+	 * the one returned by the overriden method.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0;
-+  for( int j = realSize(), i = 0; j-- != 0; ) {
-+   while( ( (key[ i ]) == (0) ) ) i++;
-+    h += it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
-+   i++;
-+  }
-+  // Zero / null have hash zero.		
-+  return h;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  final LongIterator i = iterator();
-+  s.defaultWriteObject();
-+  for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
-+ }
-+
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  n = arraySize( size, f );
-+  maxFill = maxFill( n, f );
-+  mask = n - 1;
-+  final long key[] = this.key = new long[ n + 1 ];
-+  long k;
-+  for( int i = size, pos; i-- != 0; ) {
-+   k = s.readLong();
-+   if ( ( (k) == (0) ) ) {
-+    pos = n;
-+    containsNull = true;
-+   }
-+   else {
-+    if ( ! ( (key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) )
-+     while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
-+   }
-+   key[ pos ] = k;
-+  }
-+  if ( ASSERTS ) checkTable();
-+ }
-+ private void checkTable() {}
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.NoSuchElementException;
-+import it.unimi.dsi.fastutil.PriorityQueue;
-+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Additionally, this interface strengthens {@link #comparator()}.
-+ */
-+public interface LongPriorityQueue extends PriorityQueue<Long> {
-+ /** Enqueues a new element.
-+	 *
-+	 * @param x the element to enqueue.
-+	 */
-+ void enqueue( long x );
-+ /** Dequeues the {@linkplain #first() first} element from the queue.
-+	 *
-+	 * @return the dequeued element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ long dequeueLong();
-+ /** Returns the first element of the queue.
-+	 *
-+	 * @return the first element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ long firstLong();
-+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
-+	 *
-+	 * @return the last element.
-+	 * @throws NoSuchElementException if the queue is empty.
-+	 */
-+ long lastLong();
-+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
-+	 *
-+	 * @see PriorityQueue#comparator()
-+	 */
-+ LongComparator comparator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+/** A class providing static methods and objects that do useful things with type-specific priority queues.
-+ *
-+ * @see it.unimi.dsi.fastutil.PriorityQueue
-+ */
-+public class LongPriorityQueues {
-+ private LongPriorityQueues() {}
-+ /** A synchronized wrapper class for priority queues. */
-+ public static class SynchronizedPriorityQueue implements LongPriorityQueue {
-+  final protected LongPriorityQueue q;
-+  final protected Object sync;
-+  protected SynchronizedPriorityQueue( final LongPriorityQueue q, final Object sync ) {
-+   this.q = q;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedPriorityQueue( final LongPriorityQueue q ) {
-+   this.q = q;
-+   this.sync = this;
-+  }
-+  public void enqueue( long x ) { synchronized( sync ) { q.enqueue( x ); } }
-+  public long dequeueLong() { synchronized( sync ) { return q.dequeueLong(); } }
-+  public long firstLong() { synchronized( sync ) { return q.firstLong(); } }
-+  public long lastLong() { synchronized( sync ) { return q.lastLong(); } }
-+  public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
-+  public int size() { synchronized( sync ) { return q.size(); } }
-+  public void clear() { synchronized( sync ) { q.clear(); } }
-+  public void changed() { synchronized( sync ) { q.changed(); } }
-+  public LongComparator comparator() { synchronized( sync ) { return q.comparator(); } }
-+  public void enqueue( Long x ) { synchronized( sync ) { q.enqueue( x ); } }
-+  public Long dequeue() { synchronized( sync ) { return q.dequeue(); } }
-+  public Long first() { synchronized( sync ) { return q.first(); } }
-+  public Long last() { synchronized( sync ) { return q.last(); } }
-+ }
-+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+ public static LongPriorityQueue synchronize( final LongPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
-+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
-+	 *
-+	 * @param q the priority queue to be wrapped in a synchronized priority queue.
-+	 * @param sync an object that will be used to synchronize the access to the priority queue.
-+	 * @return a synchronized view of the specified priority queue.
-+	 */
-+ public static LongPriorityQueue synchronize( final LongPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Set;
-+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
-+ *
-+ * @see Set
-+ */
-+public interface LongSet extends LongCollection , Set<Long> {
-+ /** Returns a type-specific iterator on the elements of this set.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
-+	 * which was already strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Set}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this set.
-+	 */
-+ LongIterator iterator();
-+ /** Removes an element from this set.
-+	 *
-+	 * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
-+	 * This unfortunate situation is caused by the clash
-+	 * with the similarly named index-based method in the {@link java.util.List} interface.
-+	 *
-+	 * @see java.util.Collection#remove(Object)
-+	 */
-+ public boolean remove( long k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.Collection;
-+import java.util.Set;
-+/** A class providing static methods and objects that do useful things with type-specific sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class LongSets {
-+ private LongSets() {}
-+ /** An immutable class representing the empty set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.
-+	 */
-+ public static class EmptySet extends LongCollections.EmptyCollection implements LongSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
-+  public Object clone() { return EMPTY_SET; }
-+  @SuppressWarnings("rawtypes")
-+  public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty set (immutable). It is serializable and cloneable.
-+	 */
-+
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** An immutable class representing a type-specific singleton set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.	 */
-+ public static class Singleton extends AbstractLongSet implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final long element;
-+  protected Singleton( final long element ) {
-+   this.element = element;
-+  }
-+  public boolean add( final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final long k ) { return ( (k) == (element) ); }
-+  public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
-+  public long[] toLongArray() {
-+   long a[] = new long[ 1 ];
-+   a[ 0 ] = element;
-+   return a;
-+  }
-+  public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
-+  public LongListIterator iterator() { return LongIterators.singleton( element ); }
-+  public int size() { return 1; }
-+  public Object clone() { return this; }
-+ }
-+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned set.
-+	 * @return a type-specific immutable set containing just <code>element</code>.
-+	 */
-+ public static LongSet singleton( final long element ) {
-+  return new Singleton ( element );
-+ }
-+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned set.
-+	 * @return a type-specific immutable set containing just <code>element</code>.
-+	 */
-+ public static LongSet singleton( final Long element ) {
-+  return new Singleton ( ((element).longValue()) );
-+ }
-+ /** A synchronized wrapper class for sets. */
-+ public static class SynchronizedSet extends LongCollections.SynchronizedCollection implements LongSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected SynchronizedSet( final LongSet s, final Object sync ) {
-+   super( s, sync );
-+  }
-+  protected SynchronizedSet( final LongSet s ) {
-+   super( s );
-+  }
-+  public boolean remove( final long k ) { synchronized( sync ) { return collection.remove( (Long.valueOf(k)) ); } }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
-+  public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
-+ }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static LongSet synchronize( final LongSet s ) { return new SynchronizedSet ( s ); }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @param sync an object that will be used to synchronize the access to the set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static LongSet synchronize( final LongSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
-+ /** An unmodifiable wrapper class for sets. */
-+ public static class UnmodifiableSet extends LongCollections.UnmodifiableCollection implements LongSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected UnmodifiableSet( final LongSet s ) {
-+   super( s );
-+  }
-+  public boolean remove( final long k ) { throw new UnsupportedOperationException(); }
-+  public boolean equals( final Object o ) { return collection.equals( o ); }
-+  public int hashCode() { return collection.hashCode(); }
-+ }
-+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in an unmodifiable set.
-+	 * @return an unmodifiable view of the specified set.
-+	 * @see java.util.Collections#unmodifiableSet(Set)
-+	 */
-+ public static LongSet unmodifiable( final LongSet s ) { return new UnmodifiableSet ( s ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.SortedSet;
-+import java.util.Collection;
-+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #iterator()},
-+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)}, 
-+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
-+ *
-+ * @see SortedSet
-+ */
-+public interface LongSortedSet extends LongSet , SortedSet<Long> {
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set, starting from a given element of the domain (optional operation).
-+	 *
-+	 * <P>This method returns a type-specific bidirectional iterator with given
-+	 * starting point. The starting point is any element comparable to the
-+	 * elements of this set (even if it does not actually belong to the
-+	 * set). The next element of the returned iterator is the least element of
-+	 * the set that is greater than the starting point (if there are no
-+	 * elements greater than the starting point, {@link
-+	 * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
-+	 * <code>false</code>). The previous element of the returned iterator is
-+	 * the greatest element of the set that is smaller than or equal to the
-+	 * starting point (if there are no elements smaller than or equal to the
-+	 * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
-+	 * hasPrevious()} will return <code>false</code>).
-+	 *  
-+	 * <P>Note that passing the last element of the set as starting point and
-+	 * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
-+	 * entire set in reverse order.
-+	 *
-+	 * @param fromElement an element to start from.
-+	 * @return a bidirectional iterator on the element in this set, starting at the given element.
-+	 * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
-+	 */
-+ LongBidirectionalIterator iterator( long fromElement );
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
-+	 *
-+	 * <P>The iterator returned by the {@link #iterator()} method and by this
-+	 * method are identical; however, using this method you can save a type casting.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ LongBidirectionalIterator longIterator();
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set.
-+	 *
-+	 * <P>This method returns a parameterised bidirectional iterator. The iterator
-+	 * can be moreover safely cast to a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @return a bidirectional iterator on the element in this set. 
-+	 */
-+ LongBidirectionalIterator iterator();
-+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
-+	 *
-+	 * @see SortedSet#subSet(Object,Object)
-+	 */
-+ LongSortedSet subSet( Long fromElement, Long toElement) ;
-+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
-+	 *
-+	 * @see SortedSet#headSet(Object)
-+	 */
-+ LongSortedSet headSet( Long toElement );
-+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
-+	 *
-+	 * @see SortedSet#tailSet(Object)
-+	 */
-+ LongSortedSet tailSet( Long fromElement );
-+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
-+	 *
-+	 * @see SortedSet#comparator()
-+	 */
-+ LongComparator comparator();
-+ /**
-+	 * @see SortedSet#subSet(Object,Object)
-+	 */
-+ LongSortedSet subSet( long fromElement, long toElement) ;
-+ /**
-+	 * @see SortedSet#headSet(Object)
-+	 */
-+ LongSortedSet headSet( long toElement );
-+ /**
-+	 * @see SortedSet#tailSet(Object)
-+	 */
-+ LongSortedSet tailSet( long fromElement );
-+ /**
-+	 * @see SortedSet#first()
-+	 */
-+ long firstLong();
-+ /**
-+	 * @see SortedSet#last()
-+	 */
-+ long lastLong();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import java.util.SortedSet;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class LongSortedSets {
-+ private LongSortedSets() {}
-+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class EmptySet extends LongSets.EmptySet implements LongSortedSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
-+  @Deprecated
-+  public LongBidirectionalIterator longIterator() { return iterator(); }
-+ 
-+  public LongBidirectionalIterator iterator( long from ) { return LongIterators.EMPTY_ITERATOR; }
-+ 
-+  public LongSortedSet subSet( long from, long to ) { return EMPTY_SET; }
-+ 
-+  public LongSortedSet headSet( long from ) { return EMPTY_SET; }
-+ 
-+  public LongSortedSet tailSet( long to ) { return EMPTY_SET; }
-+  public long firstLong() { throw new NoSuchElementException(); }
-+  public long lastLong() { throw new NoSuchElementException(); }
-+  public LongComparator comparator() { return null; }
-+  public LongSortedSet subSet( Long from, Long to ) { return EMPTY_SET; }
-+  public LongSortedSet headSet( Long from ) { return EMPTY_SET; }
-+  public LongSortedSet tailSet( Long to ) { return EMPTY_SET; }
-+  public Long first() { throw new NoSuchElementException(); }
-+  public Long last() { throw new NoSuchElementException(); }
-+  public Object clone() { return EMPTY_SET; }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty sorted set (immutable). It is serializable and cloneable.
-+	 *
-+	 */
-+
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** A class representing a singleton sorted set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class Singleton extends LongSets.Singleton implements LongSortedSet , java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  final LongComparator comparator;
-+  private Singleton( final long element, final LongComparator comparator ) {
-+   super( element );
-+   this.comparator = comparator;
-+  }
-+  private Singleton( final long element ) {
-+   this( element, null );
-+  }
-+ 
-+  final int compare( final long k1, final long k2 ) {
-+   return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
-+  }
-+  @Deprecated
-+  public LongBidirectionalIterator longIterator() {
-+   return iterator();
-+  }
-+  public LongBidirectionalIterator iterator( long from ) {
-+   LongBidirectionalIterator i = iterator();
-+   if ( compare( element, from ) <= 0 ) i.next();
-+   return i;
-+  }
-+  public LongComparator comparator() { return comparator; }
-+ 
-+  public LongSortedSet subSet( final long from, final long to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+ 
-+  public LongSortedSet headSet( final long to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+ 
-+  public LongSortedSet tailSet( final long from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
-+  public long firstLong() { return element; }
-+  public long lastLong() { return element; }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long first() { return (Long.valueOf(element)); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public Long last() { return (Long.valueOf(element)); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public LongSortedSet subSet( final Long from, final Long to ) { return subSet( ((from).longValue()), ((to).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public LongSortedSet headSet( final Long to ) { return headSet( ((to).longValue()) ); }
-+  /** {@inheritDoc}
-+		 * @deprecated Please use the corresponding type-specific method instead. */
-+  @Deprecated
-+  public LongSortedSet tailSet( final Long from ) { return tailSet( ((from).longValue()) ); }
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static LongSortedSet singleton( final long element ) {
-+  return new Singleton ( element );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @param comparator the comparator to use in the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static LongSortedSet singleton( final long element, final LongComparator comparator ) {
-+  return new Singleton ( element, comparator );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static LongSortedSet singleton( final Object element ) {
-+  return new Singleton( ((((Long)(element)).longValue())) );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @param comparator the comparator to use in the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static LongSortedSet singleton( final Object element, final LongComparator comparator ) {
-+  return new Singleton( ((((Long)(element)).longValue())), comparator );
-+ }
-+ /** A synchronized wrapper class for sorted sets. */
-+ public static class SynchronizedSortedSet extends LongSets.SynchronizedSet implements LongSortedSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongSortedSet sortedSet;
-+  protected SynchronizedSortedSet( final LongSortedSet s, final Object sync ) {
-+   super( s, sync );
-+   sortedSet = s;
-+  }
-+  protected SynchronizedSortedSet( final LongSortedSet s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public LongComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
-+  public LongSortedSet subSet( final long from, final long to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
-+  public LongSortedSet headSet( final long to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
-+  public LongSortedSet tailSet( final long from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
-+  public LongBidirectionalIterator iterator() { return sortedSet.iterator(); }
-+  public LongBidirectionalIterator iterator( final long from ) { return sortedSet.iterator( from ); }
-+  @Deprecated
-+  public LongBidirectionalIterator longIterator() { return sortedSet.iterator(); }
-+  public long firstLong() { synchronized( sync ) { return sortedSet.firstLong(); } }
-+  public long lastLong() { synchronized( sync ) { return sortedSet.lastLong(); } }
-+  public Long first() { synchronized( sync ) { return sortedSet.first(); } }
-+  public Long last() { synchronized( sync ) { return sortedSet.last(); } }
-+  public LongSortedSet subSet( final Long from, final Long to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
-+  public LongSortedSet headSet( final Long to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
-+  public LongSortedSet tailSet( final Long from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
-+ }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static LongSortedSet synchronize( final LongSortedSet s ) { return new SynchronizedSortedSet ( s ); }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @param sync an object that will be used to synchronize the access to the sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static LongSortedSet synchronize( final LongSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
-+ /** An unmodifiable wrapper class for sorted sets. */
-+ public static class UnmodifiableSortedSet extends LongSets.UnmodifiableSet implements LongSortedSet , java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final LongSortedSet sortedSet;
-+  protected UnmodifiableSortedSet( final LongSortedSet s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public LongComparator comparator() { return sortedSet.comparator(); }
-+  public LongSortedSet subSet( final long from, final long to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
-+  public LongSortedSet headSet( final long to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
-+  public LongSortedSet tailSet( final long from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
-+  public LongBidirectionalIterator iterator() { return LongIterators.unmodifiable( sortedSet.iterator() ); }
-+  public LongBidirectionalIterator iterator( final long from ) { return LongIterators.unmodifiable( sortedSet.iterator( from ) ); }
-+  @Deprecated
-+  public LongBidirectionalIterator longIterator() { return iterator(); }
-+  public long firstLong() { return sortedSet.firstLong(); }
-+  public long lastLong() { return sortedSet.lastLong(); }
-+  public Long first() { return sortedSet.first(); }
-+  public Long last() { return sortedSet.last(); }
-+  public LongSortedSet subSet( final Long from, final Long to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
-+  public LongSortedSet headSet( final Long to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
-+  public LongSortedSet tailSet( final Long from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
-+ }
-+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in an unmodifiable sorted set.
-+	 * @return an unmodifiable view of the specified sorted set.
-+	 * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
-+	 */
-+ public static LongSortedSet unmodifiable( final LongSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Primitive-type-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.longs;
-+import it.unimi.dsi.fastutil.Stack;
-+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ */
-+public interface LongStack extends Stack<Long> {
-+ /**
-+	 * @see Stack#push(Object)
-+	 */
-+ void push( long k );
-+ /**
-+	 * @see Stack#pop()
-+	 */
-+ long popLong();
-+ /** 
-+	 * @see Stack#top()
-+	 */
-+ long topLong();
-+ /** 
-+	 * @see Stack#peek(int)
-+	 */
-+ long peekLong( int i );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/package.html b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
-@@ -0,0 +0,0 @@
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-+<html>
-+  <head>
-+    <title>fastutil</title>
-+  </head>
-+
-+  <body>
-+
-+	 <P>Provides type-specific classes for long elements or keys.
-+
-+  </body>
-+</html>
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
-+ *
-+ * <P>To create a type-specific bidirectional iterator, besides what is needed
-+ * for an iterator you need both a method returning the previous element as
-+ * primitive type and a method returning the previous element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #back(int)} that
-+ * uses type-specific methods.
-+ */
-+public abstract class AbstractObjectBidirectionalIterator <K> extends AbstractObjectIterator <K> implements ObjectBidirectionalIterator <K> {
-+ protected AbstractObjectBidirectionalIterator() {}
-+ /** This method just iterates the type-specific version of {@link #previous()} for
-+	 * at most <code>n</code> times, stopping if {@link
-+	 * #hasPrevious()} becomes false. */
-+ public int back( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasPrevious() ) previous();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.AbstractCollection;
-+import java.util.Collection;
-+import java.util.Iterator;
-+/** An abstract class providing basic methods for collections implementing a type-specific interface.
-+ *
-+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
-+ * {@link #contains(Object)} methods that just call the type-specific counterpart. 
-+ */
-+public abstract class AbstractObjectCollection <K> extends AbstractCollection<K> implements ObjectCollection <K> {
-+ protected AbstractObjectCollection() {}
-+ public Object[] toArray() {
-+  final Object[] a = new Object[ size() ];
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  return a;
-+ }
-+ @SuppressWarnings("unchecked")
-+ public <T> T[] toArray( T[] a ) {
-+  final int size = size();
-+  if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
-+  it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
-+  if ( size < a.length ) a[ size ] = null;
-+  return a;
-+ }
-+ /** Adds all elements of the given collection to this collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean addAll( Collection<? extends K> c ) {
-+  boolean retVal = false;
-+  final Iterator<? extends K> i = c.iterator();
-+  int n = c.size();
-+  while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean add( K k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public ObjectIterator <K> objectIterator() {
-+  return iterator();
-+ }
-+ public abstract ObjectIterator <K> iterator();
-+ /** Checks whether this collection contains all elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection contains all elements of the argument.
-+	 */
-+ public boolean containsAll( Collection<?> c ) {
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
-+  return true;
-+ }
-+ /** Retains in this collection only elements from the given collection.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean retainAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = size();
-+  final Iterator<?> i = iterator();
-+  while( n-- != 0 ) {
-+   if ( ! c.contains( i.next() ) ) {
-+    i.remove();
-+    retVal = true;
-+   }
-+  }
-+  return retVal;
-+ }
-+ /** Remove from this collection all elements in the given collection.
-+	 * If the collection is an instance of this class, it uses faster iterators.
-+	 *
-+	 * @param c a collection.
-+	 * @return <code>true</code> if this collection changed as a result of the call.
-+	 */
-+ public boolean removeAll( Collection<?> c ) {
-+  boolean retVal = false;
-+  int n = c.size();
-+  final Iterator<?> i = c.iterator();
-+  while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
-+  return retVal;
-+ }
-+ public boolean isEmpty() {
-+  return size() == 0;
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final ObjectIterator <K> i = iterator();
-+  int n = size();
-+  Object k;
-+  boolean first = true;
-+  s.append("{");
-+  while(n-- != 0) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.next();
-+   if (this == k) s.append("(this collection)"); else
-+    s.append(String.valueOf(k));
-+  }
-+  s.append("}");
-+  return s.toString();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+/**  An abstract class facilitating the creation of type-specific iterators.
-+ *
-+ * <P>To create a type-specific iterator you need both a method returning the
-+ * next element as primitive type and a method returning the next element as an
-+ * object. However, if you inherit from this class you need just one (anyone).
-+ *
-+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
-+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
-+ * UnsupportedOperationException}.
-+ *
-+ * @see java.util.Iterator
-+ */
-+public abstract class AbstractObjectIterator <K> implements ObjectIterator <K> {
-+ protected AbstractObjectIterator() {}
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void remove() { throw new UnsupportedOperationException(); }
-+ /** This method just iterates the type-specific version of {@link #next()} for at most
-+	 * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
-+ public int skip( final int n ) {
-+  int i = n;
-+  while( i-- != 0 && hasNext() ) next();
-+  return n - i - 1;
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import it.unimi.dsi.fastutil.Stack;
-+import java.util.List;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/**  An abstract class providing basic methods for lists implementing a type-specific list interface.
-+ *
-+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
-+ */
-+public abstract class AbstractObjectList <K> extends AbstractObjectCollection <K> implements ObjectList <K>, Stack <K> {
-+ protected AbstractObjectList() {}
-+ /** Ensures that the given index is nonnegative and not greater than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
-+	 */
-+ protected void ensureIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
-+ }
-+ /** Ensures that the given index is nonnegative and smaller than the list size.
-+	 *
-+	 * @param index an index.
-+	 * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
-+	 */
-+ protected void ensureRestrictedIndex( final int index ) {
-+  if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
-+  if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
-+ }
-+ public void add( final int index, final K k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean add( final K k ) {
-+  add( size(), k );
-+  return true;
-+ }
-+ public K remove( int i ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public K set( final int index, final K k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+ public boolean addAll( int index, final Collection<? extends K> c ) {
-+  ensureIndex( index );
-+  int n = c.size();
-+  if ( n == 0 ) return false;
-+  Iterator<? extends K> i = c.iterator();
-+  while( n-- != 0 ) add( index++, i.next() );
-+  return true;
-+ }
-+ /** Delegates to a more generic method. */
-+ public boolean addAll( final Collection<? extends K> c ) {
-+  return addAll( size(), c );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public ObjectListIterator <K> objectListIterator() {
-+  return listIterator();
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public ObjectListIterator <K> objectListIterator( final int index ) {
-+  return listIterator( index );
-+ }
-+ public ObjectListIterator <K> iterator() {
-+  return listIterator();
-+ }
-+ public ObjectListIterator <K> listIterator() {
-+  return listIterator( 0 );
-+ }
-+ public ObjectListIterator <K> listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractObjectListIterator <K>() {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < AbstractObjectList.this.size(); }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = pos++ ); }
-+    public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = --pos ); }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( K k ) {
-+     AbstractObjectList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( K k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractObjectList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     AbstractObjectList.this.remove( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public boolean contains( final Object k ) {
-+  return indexOf( k ) >= 0;
-+ }
-+ public int indexOf( final Object k ) {
-+  final ObjectListIterator <K> i = listIterator();
-+  K e;
-+  while( i.hasNext() ) {
-+   e = i.next();
-+   if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.previousIndex();
-+  }
-+  return -1;
-+ }
-+ public int lastIndexOf( final Object k ) {
-+  ObjectListIterator <K> i = listIterator( size() );
-+  K e;
-+  while( i.hasPrevious() ) {
-+   e = i.previous();
-+   if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.nextIndex();
-+  }
-+  return -1;
-+ }
-+ public void size( final int size ) {
-+  int i = size();
-+  if ( size > i ) while( i++ < size ) add( (null) );
-+  else while( i-- != size ) remove( i );
-+ }
-+ public ObjectList <K> subList( final int from, final int to ) {
-+  ensureIndex( from );
-+  ensureIndex( to );
-+  if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  return new ObjectSubList <K>( this, from, to );
-+ }
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public ObjectList <K> objectSubList( final int from, final int to ) {
-+  return subList( from, to );
-+ }
-+ /** Removes elements of this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  ensureIndex( to );
-+  ObjectListIterator <K> i = listIterator( from );
-+  int n = to - from;
-+  if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+  while( n-- != 0 ) {
-+   i.next();
-+   i.remove();
-+  }
-+ }
-+ /** Adds elements to this type-specific list one-by-one. 
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( int index, final K a[], int offset, int length ) {
-+  ensureIndex( index );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  while( length-- != 0 ) add( index++, a[ offset++ ] );
-+ }
-+ public void addElements( final int index, final K a[] ) {
-+  addElements( index, a, 0, a.length );
-+ }
-+ /** Copies element of this type-specific list into the given array one-by-one.
-+	 *
-+	 * <P>This is a trivial iterator-based implementation. It is expected that
-+	 * implementations will override this method with a more optimized version.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final Object a[], int offset, int length ) {
-+  ObjectListIterator <K> i = listIterator( from );
-+  if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
-+  if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
-+  if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
-+  while( length-- != 0 ) a[ offset++ ] = i.next();
-+ }
-+ private boolean valEquals( final Object a, final Object b ) {
-+  return a == null ? b == null : a.equals( b );
-+ }
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( ! ( o instanceof List ) ) return false;
-+  final List<?> l = (List<?>)o;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
-+  while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
-+  return true;
-+ }
-+    /** Compares this list to another object. If the
-+     * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
-+     * it throws a <code>ClassCastException</code>.
-+     *
-+     * @param l a list.
-+     * @return if the argument is a {@link java.util.List}, a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     * @throws ClassCastException if the argument is not a list.
-+     */
-+ @SuppressWarnings("unchecked")
-+ public int compareTo( final List<? extends K> l ) {
-+  if ( l == this ) return 0;
-+  if ( l instanceof ObjectList ) {
-+   final ObjectListIterator <K> i1 = listIterator(), i2 = ((ObjectList <K>)l).listIterator();
-+   int r;
-+   K e1, e2;
-+   while( i1.hasNext() && i2.hasNext() ) {
-+    e1 = i1.next();
-+    e2 = i2.next();
-+    if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
-+   }
-+   return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+  }
-+  ListIterator<? extends K> i1 = listIterator(), i2 = l.listIterator();
-+  int r;
-+  while( i1.hasNext() && i2.hasNext() ) {
-+   if ( ( r = ((Comparable<? super K>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
-+  }
-+  return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
-+ }
-+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
-+	 *
-+	 * @return the hash code for this list.
-+	 */
-+ public int hashCode() {
-+  ObjectIterator <K> i = iterator();
-+  int h = 1, s = size();
-+  while ( s-- != 0 ) {
-+   K k = i.next();
-+   h = 31 * h + ( (k) == null ? 0 : (k).hashCode() );
-+  }
-+  return h;
-+ }
-+ public void push( K o ) {
-+  add( o );
-+ }
-+ public K pop() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return remove( size() - 1 );
-+ }
-+ public K top() {
-+  if ( isEmpty() ) throw new NoSuchElementException();
-+  return get( size() - 1 );
-+ }
-+ public K peek( int i ) {
-+  return get( size() - 1 - i );
-+ }
-+ public String toString() {
-+  final StringBuilder s = new StringBuilder();
-+  final ObjectIterator <K> i = iterator();
-+  int n = size();
-+  K k;
-+  boolean first = true;
-+  s.append("[");
-+  while( n-- != 0 ) {
-+   if (first) first = false;
-+   else s.append(", ");
-+   k = i.next();
-+   if (this == k) s.append("(this list)"); else
-+    s.append( String.valueOf( k ) );
-+  }
-+  s.append("]");
-+  return s.toString();
-+ }
-+ public static class ObjectSubList <K> extends AbstractObjectList <K> implements java.io.Serializable {
-+     private static final long serialVersionUID = -7046029254386353129L;
-+  /** The list this sublist restricts. */
-+  protected final ObjectList <K> l;
-+  /** Initial (inclusive) index of this sublist. */
-+  protected final int from;
-+  /** Final (exclusive) index of this sublist. */
-+  protected int to;
-+  private static final boolean ASSERTS = false;
-+  public ObjectSubList( final ObjectList <K> l, final int from, final int to ) {
-+   this.l = l;
-+   this.from = from;
-+   this.to = to;
-+  }
-+  private void assertRange() {
-+   if ( ASSERTS ) {
-+    assert from <= l.size();
-+    assert to <= l.size();
-+    assert to >= from;
-+   }
-+  }
-+  public boolean add( final K k ) {
-+   l.add( to, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+   return true;
-+  }
-+  public void add( final int index, final K k ) {
-+   ensureIndex( index );
-+   l.add( from + index, k );
-+   to++;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public boolean addAll( final int index, final Collection<? extends K> c ) {
-+   ensureIndex( index );
-+   to += c.size();
-+   if ( ASSERTS ) {
-+    boolean retVal = l.addAll( from + index, c );
-+    assertRange();
-+    return retVal;
-+   }
-+   return l.addAll( from + index, c );
-+  }
-+  public K get( int index ) {
-+   ensureRestrictedIndex( index );
-+   return l.get( from + index );
-+  }
-+  public K remove( int index ) {
-+   ensureRestrictedIndex( index );
-+   to--;
-+   return l.remove( from + index );
-+  }
-+  public K set( int index, K k ) {
-+   ensureRestrictedIndex( index );
-+   return l.set( from + index, k );
-+  }
-+  public void clear() {
-+   removeElements( 0, size() );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public int size() {
-+   return to - from;
-+  }
-+  public void getElements( final int from, final Object[] a, final int offset, final int length ) {
-+   ensureIndex( from );
-+   if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
-+   l.getElements( this.from + from, a, offset, length );
-+  }
-+  public void removeElements( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   l.removeElements( this.from + from, this.from + to );
-+   this.to -= ( to - from );
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public void addElements( int index, final K a[], int offset, int length ) {
-+   ensureIndex( index );
-+   l.addElements( this.from + index, a, offset, length );
-+   this.to += length;
-+   if ( ASSERTS ) assertRange();
-+  }
-+  public ObjectListIterator <K> listIterator( final int index ) {
-+   ensureIndex( index );
-+   return new AbstractObjectListIterator <K>() {
-+     int pos = index, last = -1;
-+     public boolean hasNext() { return pos < size(); }
-+     public boolean hasPrevious() { return pos > 0; }
-+     public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.get( from + ( last = pos++ ) ); }
-+     public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.get( from + ( last = --pos ) ); }
-+     public int nextIndex() { return pos; }
-+     public int previousIndex() { return pos - 1; }
-+     public void add( K k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      ObjectSubList.this.add( pos++, k );
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+     public void set( K k ) {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      ObjectSubList.this.set( last, k );
-+     }
-+     public void remove() {
-+      if ( last == -1 ) throw new IllegalStateException();
-+      ObjectSubList.this.remove( last );
-+      /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+      if ( last < pos ) pos--;
-+      last = -1;
-+      if ( ASSERTS ) assertRange();
-+     }
-+    };
-+  }
-+  public ObjectList <K> subList( final int from, final int to ) {
-+   ensureIndex( from );
-+   ensureIndex( to );
-+   if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
-+   return new ObjectSubList <K>( this, from, to );
-+  }
-+  public boolean remove( final Object o ) {
-+   int index = indexOf( o );
-+   if ( index == -1 ) return false;
-+   remove( index );
-+   return true;
-+  }
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+/**  An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
-+ *
-+ * <P>This class provides trivial type-specific implementations of {@link
-+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
-+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
-+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
-+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
-+ * 
-+ *
-+ * @see java.util.ListIterator
-+ */
-+public abstract class AbstractObjectListIterator <K> extends AbstractObjectBidirectionalIterator <K> implements ObjectListIterator <K> {
-+ protected AbstractObjectListIterator() {}
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void set( K k ) { throw new UnsupportedOperationException(); }
-+ /** This method just throws an  {@link UnsupportedOperationException}. */
-+ public void add( K k ) { throw new UnsupportedOperationException(); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Set;
-+/**  An abstract class providing basic methods for sets implementing a type-specific interface. */
-+public abstract class AbstractObjectSet <K> extends AbstractObjectCollection <K> implements Cloneable, ObjectSet <K> {
-+ protected AbstractObjectSet() {}
-+ public abstract ObjectIterator <K> iterator();
-+ public boolean equals( final Object o ) {
-+  if ( o == this ) return true;
-+  if ( !( o instanceof Set ) ) return false;
-+  Set<?> s = (Set<?>) o;
-+  if ( s.size() != size() ) return false;
-+  return containsAll(s);
-+ }
-+ /** Returns a hash code for this set.
-+	 *
-+	 * The hash code of a set is computed by summing the hash codes of
-+	 * its elements.
-+	 *
-+	 * @return a hash code for this set.
-+	 */
-+ public int hashCode() {
-+  int h = 0, n = size();
-+  ObjectIterator <K> i = iterator();
-+  K k;
-+  while( n-- != 0 ) {
-+   k = i.next(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
-+   h += ( (k) == null ? 0 : (k).hashCode() );
-+  }
-+  return h;
-+ }
-+ public boolean remove( Object k ) {
-+  throw new UnsupportedOperationException();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2003-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
-+public abstract class AbstractObjectSortedSet <K> extends AbstractObjectSet <K> implements ObjectSortedSet <K> {
-+ protected AbstractObjectSortedSet() {}
-+ /** Delegates to the new covariantly stronger generic method. */
-+ @Deprecated
-+ public ObjectBidirectionalIterator <K> objectIterator() {
-+  return iterator();
-+ }
-+ public abstract ObjectBidirectionalIterator <K> iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Arrays;
-+import java.util.Collection;
-+import java.util.Iterator;
-+import java.util.RandomAccess;
-+import java.util.NoSuchElementException;
-+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>This class implements a lightweight, fast, open, optimized,
-+ * reuse-oriented version of array-based lists. Instances of this class
-+ * represent a list with an array that is enlarged as needed when new entries
-+ * are created (by doubling the current length), but is
-+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
-+ * {@linkplain #trim() trimming methods} lets you control the size of the
-+ * backing array; this is particularly useful if you reuse instances of this class.
-+ * Range checks are equivalent to those of {@link java.util}'s classes, but
-+ * they are delayed as much as possible. 
-+ *
-+ * <p>The backing array is exposed by the {@link #elements()} method. If an instance
-+ * of this class was created {@linkplain #wrap(Object[],int) by wrapping}, 
-+ * backing-array reallocations will be performed using reflection, so that
-+ * {@link #elements()} can return an array of the same type of the original array: the comments
-+ * about efficiency made in {@link it.unimi.dsi.fastutil.objects.ObjectArrays} apply here.
-+ * Moreover, you must take into consideration that assignment to an array
-+ * not of type {@code Object[]} is slower due to type checking.
-+ *
-+ * <p>This class implements the bulk methods <code>removeElements()</code>,
-+ * <code>addElements()</code> and <code>getElements()</code> using
-+ * high-performance system calls (e.g., {@link
-+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
-+ * expensive loops.
-+ *
-+ * @see java.util.ArrayList
-+ */
-+public class ObjectArrayList <K> extends AbstractObjectList <K> implements RandomAccess, Cloneable, java.io.Serializable {
-+ private static final long serialVersionUID = -7046029254386353131L;
-+ /** The initial default capacity of an array list. */
-+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
-+ /** Whether the backing array was passed to <code>wrap()</code>. In
-+	 * this case, we must reallocate with the same type of array. */
-+ protected final boolean wrapped;
-+ /** The backing array. */
-+ protected transient K a[];
-+ /** The current actual size of the list (never greater than the backing-array length). */
-+ protected int size;
-+ private static final boolean ASSERTS = false;
-+ /** Creates a new array list using a given array.
-+	 *
-+	 * <P>This constructor is only meant to be used by the wrapping methods.
-+	 *
-+	 * @param a the array that will be used to back this array list.
-+	 */
-+ @SuppressWarnings("unused")
-+ protected ObjectArrayList( final K a[], boolean dummy ) {
-+  this.a = a;
-+  this.wrapped = true;
-+ }
-+ /** Creates a new array list with given capacity.
-+	 *
-+	 * @param capacity the initial capacity of the array list (may be 0).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public ObjectArrayList( final int capacity ) {
-+  if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
-+  a = (K[]) new Object[ capacity ];
-+  wrapped = false;
-+ }
-+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
-+	 */
-+ public ObjectArrayList() {
-+  this( DEFAULT_INITIAL_CAPACITY );
-+ }
-+ /** Creates a new array list and fills it with a given collection.
-+	 *
-+	 * @param c a collection that will be used to fill the array list.
-+	 */
-+ public ObjectArrayList( final Collection<? extends K> c ) {
-+  this( c.size() );
-+  size = ObjectIterators.unwrap( c.iterator(), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific collection.
-+	 *
-+	 * @param c a type-specific collection that will be used to fill the array list.
-+	 */
-+ public ObjectArrayList( final ObjectCollection <? extends K> c ) {
-+  this( c.size() );
-+  size = ObjectIterators.unwrap( c.iterator(), a );
-+ }
-+ /** Creates a new array list and fills it with a given type-specific list.
-+	 *
-+	 * @param l a type-specific list that will be used to fill the array list.
-+	 */
-+ public ObjectArrayList( final ObjectList <? extends K> l ) {
-+  this( l.size() );
-+  l.getElements( 0, a, 0, size = l.size() );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 */
-+ public ObjectArrayList( final K a[] ) {
-+  this( a, 0, a.length );
-+ }
-+ /** Creates a new array list and fills it with the elements of a given array.
-+	 *
-+	 * @param a an array whose elements will be used to fill the array list.
-+	 * @param offset the first element to use.
-+	 * @param length the number of elements to use.
-+	 */
-+ public ObjectArrayList( final K a[], final int offset, final int length ) {
-+  this( length );
-+  System.arraycopy( a, offset, this.a, 0, length );
-+  size = length;
-+ }
-+ /** Creates a new array list and fills it with the elements returned by an iterator..
-+	 *
-+	 * @param i an iterator whose returned elements will fill the array list.
-+	 */
-+ public ObjectArrayList( final Iterator<? extends K> i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.next() );
-+ }
-+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
-+	 *
-+	 * @param i a type-specific iterator whose returned elements will fill the array list.
-+	 */
-+ public ObjectArrayList( final ObjectIterator <? extends K> i ) {
-+  this();
-+  while( i.hasNext() ) this.add( i.next() );
-+ }
-+ /** Returns the backing array of this list.
-+	 *
-+	 * <P>If this array list was created by wrapping a given array, it is guaranteed
-+	 * that the type of the returned array will be the same. Otherwise, the returned
-+	 * array will be of type {@link Object Object[]} (in spite of the declared return type).
-+	 * 
-+	 * <P><strong>Warning</strong>: This behaviour may cause (unfathomable) 
-+	 * run-time errors if a method expects an array
-+	 * actually of type <code>K[]</code>, but this methods returns an array
-+	 * of type {@link Object Object[]}.
-+	 *
-+	 * @return the backing array.
-+	 */
-+ public K[] elements() {
-+  return a;
-+ }
-+ /** Wraps a given array into an array list of given size.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @param length the length of the resulting array list.
-+	 * @return a new array list of the given size, wrapping the given array.
-+	 */
-+ public static <K> ObjectArrayList <K> wrap( final K a[], final int length ) {
-+  if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
-+  final ObjectArrayList <K> l = new ObjectArrayList <K>( a, false );
-+  l.size = length;
-+  return l;
-+ }
-+ /** Wraps a given array into an array list.
-+	 *
-+	 * <P>Note it is guaranteed
-+	 * that the type of the array returned by {@link #elements()} will be the same
-+	 * (see the comments in the class documentation).
-+	 *
-+	 * @param a an array to wrap.
-+	 * @return a new array list wrapping the given array.
-+	 */
-+ public static <K> ObjectArrayList <K> wrap( final K a[] ) {
-+  return wrap( a, a.length );
-+ }
-+ /** Ensures that this array list can contain the given number of entries without resizing.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public void ensureCapacity( final int capacity ) {
-+  if ( wrapped ) a = ObjectArrays.ensureCapacity( a, capacity, size );
-+  else {
-+   if ( capacity > a.length ) {
-+    final Object t[] = new Object[ capacity ];
-+    System.arraycopy( a, 0, t, 0, size );
-+    a = (K[])t;
-+   }
-+  }
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
-+	 * and in case enlarging it at least by a factor of two.
-+	 *
-+	 * @param capacity the new minimum capacity for this array list.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ private void grow( final int capacity ) {
-+  if ( wrapped ) a = ObjectArrays.grow( a, capacity, size );
-+  else {
-+   if ( capacity > a.length ) {
-+    final int newLength = (int)Math.max( Math.min( 2L * a.length, it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE ), capacity );
-+    final Object t[] = new Object[ newLength ];
-+    System.arraycopy( a, 0, t, 0, size );
-+    a = (K[])t;
-+   }
-+  }
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public void add( final int index, final K k ) {
-+  ensureIndex( index );
-+  grow( size + 1 );
-+  if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
-+  a[ index ] = k;
-+  size++;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public boolean add( final K k ) {
-+  grow( size + 1 );
-+  a[ size++ ] = k;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public K get( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  return a[ index ];
-+ }
-+ public int indexOf( final Object k ) {
-+  for( int i = 0; i < size; i++ ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public int lastIndexOf( final Object k ) {
-+  for( int i = size; i-- != 0; ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
-+  return -1;
-+ }
-+ public K remove( final int index ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  final K old = a[ index ];
-+  size--;
-+  if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
-+  a[ size ] = null;
-+  if ( ASSERTS ) assert size <= a.length;
-+  return old;
-+ }
-+ public boolean rem( final Object k ) {
-+  int index = indexOf( k );
-+  if ( index == -1 ) return false;
-+  remove( index );
-+  if ( ASSERTS ) assert size <= a.length;
-+  return true;
-+ }
-+ public boolean remove( final Object o ) {
-+  return rem( o );
-+ }
-+ public K set( final int index, final K k ) {
-+  if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
-+  K old = a[ index ];
-+  a[ index ] = k;
-+  return old;
-+ }
-+ public void clear() {
-+  Arrays.fill( a, 0, size, null );
-+  size = 0;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ public void size( final int size ) {
-+  if ( size > a.length ) ensureCapacity( size );
-+  if ( size > this.size ) Arrays.fill( a, this.size, size, (null) );
-+  else Arrays.fill( a, size, this.size, (null) );
-+  this.size = size;
-+ }
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Trims this array list so that the capacity is equal to the size. 
-+	 *
-+	 * @see java.util.ArrayList#trimToSize()
-+	 */
-+ public void trim() {
-+  trim( 0 );
-+ }
-+ /** Trims the backing array if it is too large.
-+	 * 
-+	 * If the current array length is smaller than or equal to
-+	 * <code>n</code>, this method does nothing. Otherwise, it trims the
-+	 * array length to the maximum between <code>n</code> and {@link #size()}.
-+	 *
-+	 * <P>This method is useful when reusing lists.  {@linkplain #clear() Clearing a
-+	 * list} leaves the array length untouched. If you are reusing a list
-+	 * many times, you can call this method with a typical
-+	 * size to avoid keeping around a very large array just
-+	 * because of a few large transient lists.
-+	 *
-+	 * @param n the threshold for the trimming.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public void trim( final int n ) {
-+  // TODO: use Arrays.trim() and preserve type only if necessary
-+  if ( n >= a.length || size == a.length ) return;
-+  final K t[] = (K[]) new Object[ Math.max( n, size ) ];
-+  System.arraycopy( a, 0, t, 0, size );
-+  a = t;
-+  if ( ASSERTS ) assert size <= a.length;
-+ }
-+    /** Copies element of this type-specific list into the given array using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ public void getElements( final int from, final Object[] a, final int offset, final int length ) {
-+  ObjectArrays.ensureOffsetLength( a, offset, length );
-+  System.arraycopy( this.a, from, a, offset, length );
-+ }
-+ /** Removes elements of this type-specific list using optimized system calls.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ public void removeElements( final int from, final int to ) {
-+  it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
-+  System.arraycopy( a, to, a, from, size - to );
-+  size -= ( to - from );
-+  int i = to - from;
-+  while( i-- != 0 ) a[ size + i ] = null;
-+ }
-+ /** Adds elements to this type-specific list using optimized system calls.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ public void addElements( final int index, final K a[], final int offset, final int length ) {
-+  ensureIndex( index );
-+  ObjectArrays.ensureOffsetLength( a, offset, length );
-+  grow( size + length );
-+  System.arraycopy( this.a, index, this.a, index + length, size - index );
-+  System.arraycopy( a, offset, this.a, index, length );
-+  size += length;
-+ }
-+ @Override
-+ public boolean removeAll( final Collection<?> c ) {
-+  final Object[] a = this.a;
-+  int j = 0;
-+  for( int i = 0; i < size; i++ )
-+   if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
-+  Arrays.fill( a, j, size, null );
-+  final boolean modified = size != j;
-+  size = j;
-+  return modified;
-+ }
-+ public ObjectListIterator <K> listIterator( final int index ) {
-+  ensureIndex( index );
-+  return new AbstractObjectListIterator <K>() {
-+    int pos = index, last = -1;
-+    public boolean hasNext() { return pos < size; }
-+    public boolean hasPrevious() { return pos > 0; }
-+    public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
-+    public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
-+    public int nextIndex() { return pos; }
-+    public int previousIndex() { return pos - 1; }
-+    public void add( K k ) {
-+     ObjectArrayList.this.add( pos++, k );
-+     last = -1;
-+    }
-+    public void set( K k ) {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     ObjectArrayList.this.set( last, k );
-+    }
-+    public void remove() {
-+     if ( last == -1 ) throw new IllegalStateException();
-+     ObjectArrayList.this.remove( last );
-+     /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
-+     if ( last < pos ) pos--;
-+     last = -1;
-+    }
-+   };
-+ }
-+ public ObjectArrayList <K> clone() {
-+  ObjectArrayList <K> c = new ObjectArrayList <K>( size );
-+  System.arraycopy( a, 0, c.a, 0, size );
-+  c.size = size;
-+  return c;
-+ }
-+ private boolean valEquals( final K a, final K b ) {
-+  return a == null ? b == null : a.equals( b );
-+ }
-+    /** Compares this type-specific array list to another one.
-+	 *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+	 * @param l a type-specific array list.
-+     * @return true if the argument contains the same elements of this type-specific array list.
-+	 */
-+ public boolean equals( final ObjectArrayList <K> l ) {
-+  if ( l == this ) return true;
-+  int s = size();
-+  if ( s != l.size() ) return false;
-+  final K[] a1 = a;
-+  final K[] a2 = l.a;
-+  while( s-- != 0 ) if ( ! valEquals( a1[ s ], a2[ s ] ) ) return false;
-+  return true;
-+ }
-+    /** Compares this array list to another array list.
-+     *
-+	 * <P>This method exists only for sake of efficiency. The implementation
-+	 * inherited from the abstract implementation would already work.
-+	 *
-+     * @param l an array list.
-+     * @return a negative integer,
-+     * zero, or a positive integer as this list is lexicographically less than, equal
-+     * to, or greater than the argument.
-+     */
-+ @SuppressWarnings("unchecked")
-+ public int compareTo( final ObjectArrayList <? extends K> l ) {
-+  final int s1 = size(), s2 = l.size();
-+  final K a1[] = a, a2[] = l.a;
-+  K e1, e2;
-+  int r, i;
-+  for( i = 0; i < s1 && i < s2; i++ ) {
-+   e1 = a1[ i ];
-+   e2 = a2[ i ];
-+   if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
-+  }
-+  return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
-+ }
-+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = (K[]) new Object[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = (K) s.readObject();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2007-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Collection;
-+import java.util.NoSuchElementException;
-+/** A simple, brute-force implementation of a set based on a backing array.
-+ *
-+ * <p>The main purpose of this
-+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very 
-+ * small number of items: just put them into an array and scan linearly to find an item.
-+ */
-+public class ObjectArraySet <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
-+ private static final long serialVersionUID = 1L;
-+ /** The backing array (valid up to {@link #size}, excluded). */
-+ private transient Object[] a;
-+ /** The number of valid entries in {@link #a}. */
-+ private int size;
-+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
-+	 * 
-+	 * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 */
-+ public ObjectArraySet( final Object[] a ) {
-+  this.a = a;
-+  size = a.length;
-+ }
-+ /** Creates a new empty array set.
-+	 */
-+ public ObjectArraySet() {
-+  this.a = ObjectArrays.EMPTY_ARRAY;
-+ }
-+ /** Creates a new empty array set of given initial capacity.
-+	 * 
-+	 * @param capacity the initial capacity.
-+	 */
-+ public ObjectArraySet( final int capacity ) {
-+  this.a = new Object[ capacity ];
-+ }
-+ /** Creates a new array set copying the contents of a given collection.
-+	 * @param c a collection.
-+	 */
-+ public ObjectArraySet( ObjectCollection <K> c ) {
-+  this( c.size () );
-+  addAll( c );
-+ }
-+ /** Creates a new array set copying the contents of a given set.
-+	 * @param c a collection.
-+	 */
-+ public ObjectArraySet( final Collection<? extends K> c ) {
-+  this( c.size() );
-+  addAll( c );
-+ }
-+ /** Creates a new array set using the given backing array and the given number of elements of the array.
-+	 *
-+	 * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
-+	 * 
-+	 * @param a the backing array.
-+	 * @param size the number of valid elements in <code>a</code>.
-+	 */
-+ public ObjectArraySet( final Object[] a, final int size ) {
-+  this.a = a;
-+  this.size = size;
-+  if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
-+ }
-+ private int findKey( final Object o ) {
-+  for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == null ? (o) == null : (a[ i ]).equals(o) ) ) return i;
-+  return -1;
-+ }
-+ @Override
-+ @SuppressWarnings("unchecked")
-+ public ObjectIterator <K> iterator() {
-+  return new AbstractObjectIterator <K> () {
-+   int next = 0;
-+   public boolean hasNext() {
-+    return next < size;
-+   }
-+   public K next() {
-+    if ( ! hasNext() ) throw new NoSuchElementException();
-+    return (K) a[ next++ ];
-+   }
-+   public void remove() {
-+    final int tail = size-- - next--;
-+    System.arraycopy( a, next + 1, a, next, tail );
-+    a[ size ] = null;
-+   }
-+  };
-+ }
-+ public boolean contains( final Object k ) {
-+  return findKey( k ) != -1;
-+ }
-+ public int size() {
-+  return size;
-+ }
-+ @Override
-+ public boolean remove( final Object k ) {
-+  final int pos = findKey( k );
-+  if ( pos == -1 ) return false;
-+  final int tail = size - pos - 1;
-+  for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
-+  size--;
-+  a[ size ] = null;
-+  return true;
-+ }
-+ @Override
-+ public boolean add( final K k ) {
-+  final int pos = findKey( k );
-+  if ( pos != -1 ) return false;
-+  if ( size == a.length ) {
-+   final Object[] b = new Object[ size == 0 ? 2 : size * 2 ];
-+   for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
-+   a = b;
-+  }
-+  a[ size++ ] = k;
-+  return true;
-+ }
-+ @Override
-+ public void clear() {
-+  for( int i = size; i-- != 0; ) a[ i ] = null;
-+  size = 0;
-+ }
-+ @Override
-+ public boolean isEmpty() {
-+  return size == 0;
-+ }
-+ /** Returns a deep copy of this set. 
-+	 *
-+	 * <P>This method performs a deep copy of this hash set; the data stored in the
-+	 * set, however, is not cloned. Note that this makes a difference only for object keys.
-+	 *
-+	 *  @return a deep copy of this set.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public ObjectArraySet <K> clone() {
-+  ObjectArraySet <K> c;
-+  try {
-+   c = (ObjectArraySet <K>)super.clone();
-+  }
-+  catch(CloneNotSupportedException cantHappen) {
-+   throw new InternalError();
-+  }
-+  c.a = a.clone();
-+  return c;
-+ }
-+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
-+  s.defaultWriteObject();
-+  for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
-+ }
-+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
-+  s.defaultReadObject();
-+  a = new Object[ size ];
-+  for( int i = 0; i < size; i++ ) a[ i ] = s.readObject();
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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. 
-+ *
-+ *
-+ *
-+ * For the sorting and binary search code:
-+ *
-+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
-+ *
-+ *   Permission to use, copy, modify, distribute and sell this software and
-+ *   its documentation for any purpose is hereby granted without fee,
-+ *   provided that the above copyright notice appear in all copies and that
-+ *   both that copyright notice and this permission notice appear in
-+ *   supporting documentation. CERN makes no representations about the
-+ *   suitability of this software for any purpose. It is provided "as is"
-+ *   without expressed or implied warranty. 
-+ */
-+package it.unimi.dsi.fastutil.objects;
-+import it.unimi.dsi.fastutil.Arrays;
-+import it.unimi.dsi.fastutil.Hash;
-+import java.util.Random;
-+import java.util.concurrent.ForkJoinPool;
-+import java.util.concurrent.RecursiveAction;
-+import it.unimi.dsi.fastutil.ints.IntArrays;
-+import java.util.Comparator;
-+/** A class providing static methods and objects that do useful things with type-specific arrays.
-+ *
-+ * In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
-+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
-+ * arrays much like array lists. This can be very useful when efficiency (or
-+ * syntactic simplicity) reasons make array lists unsuitable.
-+ *
-+ * <P><strong>Warning:</strong> if your array is not of type {@code Object[]},
-+ * {@link #ensureCapacity(Object[],int,int)} and {@link #grow(Object[],int,int)}
-+ * will use {@linkplain java.lang.reflect.Array#newInstance(Class,int) reflection}
-+ * to preserve your array type. Reflection is <em>significantly slower</em> than using <code>new</code>. 
-+ * This phenomenon is particularly
-+ * evident in the first growth phases of an array reallocated with doubling (or similar) logic.
-+ *
-+ * <h2>Sorting</h2>
-+ *
-+ * <p>There are several sorting methods available. The main theme is that of letting you choose
-+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
-+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
-+ *
-+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
-+ *
-+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated), 
-+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
-+ * are about 50% faster than the classical single-pivot implementation used here.
-+ *
-+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
-+ * with your data distribution and on your architecture.
-+ * 
-+ * @see java.util.Arrays
-+ */
-+public class ObjectArrays {
-+ private ObjectArrays() {}
-+ /** A static, final, empty array. */
-+ public final static Object[] EMPTY_ARRAY = {};
-+ /** Creates a new array using a the given one as prototype. 
-+	 *
-+	 * <P>This method returns a new array of the given length whose element
-+	 * are of the same class as of those of <code>prototype</code>. In case
-+	 * of an empty array, it tries to return {@link #EMPTY_ARRAY}, if possible.
-+	 *
-+	 * @param prototype an array that will be used to type the new one.
-+	 * @param length the length of the new array.
-+	 * @return a new array of given type and length.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ private static <K> K[] newArray( final K[] prototype, final int length ) {
-+  final Class<?> klass = prototype.getClass();
-+  if ( klass == Object[].class ) return (K[])( length == 0 ? EMPTY_ARRAY : new Object[ length ] );
-+  return (K[])java.lang.reflect.Array.newInstance( klass.getComponentType(), length );
-+ }
-+ /** Ensures that an array can contain the given number of entries.
-+	 *
-+	 * <P>If you cannot foresee whether this array will need again to be
-+	 * enlarged, you should probably use <code>grow()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>array.length</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static <K> K[] ensureCapacity( final K[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final K t[] =
-+    newArray( array, length );
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
-+	 * an array with <code>length</code> entries whose first <code>preserve</code>
-+	 * entries are the same as those of <code>array</code>.
-+	 */
-+ public static <K> K[] ensureCapacity( final K[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final K t[] =
-+    newArray( array, length );
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>array.length</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static <K> K[] grow( final K[] array, final int length ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final K t[] =
-+    newArray( array, newLength );
-+   System.arraycopy( array, 0, t, 0, array.length );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Grows the given array to the maximum between the given length and
-+	 * the current length multiplied by two, provided that the given
-+	 * length is larger than the current length, preserving just a part of the array.
-+	 *
-+	 * <P>If you want complete control on the array growth, you
-+	 * should probably use <code>ensureCapacity()</code> instead.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new minimum length for this array.
-+	 * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
-+	 * @return <code>array</code>, if it can contain <code>length</code>
-+	 * entries; otherwise, an array with
-+	 * max(<code>length</code>,<code>array.length</code>/&phi;) entries whose first
-+	 * <code>preserve</code> entries are the same as those of <code>array</code>.
-+	 * */
-+ public static <K> K[] grow( final K[] array, final int length, final int preserve ) {
-+  if ( length > array.length ) {
-+   final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
-+   final K t[] =
-+    newArray( array, newLength );
-+   System.arraycopy( array, 0, t, 0, preserve );
-+   return t;
-+  }
-+  return array;
-+ }
-+ /** Trims the given array to the given length.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new maximum length for the array.
-+	 * @return <code>array</code>, if it contains <code>length</code>
-+	 * entries or less; otherwise, an array with
-+	 * <code>length</code> entries whose entries are the same as
-+	 * the first <code>length</code> entries of <code>array</code>.
-+	 * 
-+	 */
-+ public static <K> K[] trim( final K[] array, final int length ) {
-+  if ( length >= array.length ) return array;
-+  final K t[] =
-+   newArray( array, length );
-+  System.arraycopy( array, 0, t, 0, length );
-+  return t;
-+ }
-+ /** Sets the length of the given array.
-+	 *
-+	 * @param array an array.
-+	 * @param length the new length for the array.
-+	 * @return <code>array</code>, if it contains exactly <code>length</code>
-+	 * entries; otherwise, if it contains <em>more</em> than
-+	 * <code>length</code> entries, an array with <code>length</code> entries
-+	 * whose entries are the same as the first <code>length</code> entries of
-+	 * <code>array</code>; otherwise, an array with <code>length</code> entries
-+	 * whose first <code>array.length</code> entries are the same as those of
-+	 * <code>array</code>.
-+	 * 
-+	 */
-+ public static <K> K[] setLength( final K[] array, final int length ) {
-+  if ( length == array.length ) return array;
-+  if ( length < array.length ) return trim( array, length );
-+  return ensureCapacity( array, length );
-+ }
-+ /** Returns a copy of a portion of an array.
-+	 *
-+	 * @param array an array.
-+	 * @param offset the first element to copy.
-+	 * @param length the number of elements to copy.
-+	 * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
-+	 */
-+ public static <K> K[] copy( final K[] array, final int offset, final int length ) {
-+  ensureOffsetLength( array, offset, length );
-+  final K[] a =
-+   newArray( array, length );
-+  System.arraycopy( array, offset, a, 0, length );
-+  return a;
-+ }
-+ /** Returns a copy of an array.
-+	 *
-+	 * @param array an array.
-+	 * @return a copy of <code>array</code>.
-+	 */
-+ public static <K> K[] copy( final K[] array ) {
-+  return array.clone();
-+ }
-+ /** Fills the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param value the new value for all elements of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static <K> void fill( final K[] array, final K value ) {
-+  int i = array.length;
-+  while( i-- != 0 ) array[ i ] = value;
-+ }
-+ /** Fills a portion of the given array with the given value.
-+	 *
-+	 * @param array an array.
-+	 * @param from the starting index of the portion to fill (inclusive).
-+	 * @param to the end index of the portion to fill (exclusive).
-+	 * @param value the new value for all elements of the specified portion of the array.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method.
-+	 */
-+ @Deprecated
-+ public static <K> void fill( final K[] array, final int from, int to, final K value ) {
-+  ensureFromTo( array, from, to );
-+  if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
-+  else for( int i = from; i < to; i++ ) array[ i ] = value;
-+ }
-+ /** Returns true if the two arrays are elementwise equal.
-+	 *
-+	 * @param a1 an array.
-+	 * @param a2 another array.
-+	 * @return true if the two arrays are of the same length, and their elements are equal.
-+	 * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
-+	 */
-+ @Deprecated
-+ public static <K> boolean equals( final K[] a1, final K a2[] ) {
-+  int i = a1.length;
-+  if ( i != a2.length ) return false;
-+  while( i-- != 0 ) if (! ( (a1[ i ]) == null ? (a2[ i ]) == null : (a1[ i ]).equals(a2[ i ]) ) ) return false;
-+  return true;
-+ }
-+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param from a start index (inclusive).
-+	 * @param to an end index (exclusive).
-+	 * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
-+	 */
-+ public static <K> void ensureFromTo( final K[] a, final int from, final int to ) {
-+  Arrays.ensureFromTo( a.length, from, to );
-+ }
-+ /** Ensures that a range given by an offset and a length fits an array.
-+	 *
-+	 * <P>This method may be used whenever an array range check is needed.
-+	 *
-+	 * @param a an array.
-+	 * @param offset a start index.
-+	 * @param length a length (the number of elements in the range).
-+	 * @throws IllegalArgumentException if <code>length</code> is negative.
-+	 * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
-+	 */
-+ public static <K> void ensureOffsetLength( final K[] a, final int offset, final int length ) {
-+  Arrays.ensureOffsetLength( a.length, offset, length );
-+ }
-+ /** Ensures that two arrays are of the same length.
-+	 *
-+	 * @param a an array.
-+	 * @param b another array.
-+	 * @throws IllegalArgumentException if the two argument arrays are not of the same length.
-+	 */
-+ public static <K> void ensureSameLength( final K[] a, final K[] b ) {
-+  if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
-+ }
-+ private static final int QUICKSORT_NO_REC = 16;
-+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
-+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
-+ private static final int MERGESORT_NO_REC = 16;
-+ /** Swaps two elements of an anrray.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 */
-+ public static <K> void swap( final K x[], final int a, final int b ) {
-+  final K t = x[ a ];
-+  x[ a ] = x[ b ];
-+  x[ b ] = t;
-+ }
-+ /** Swaps two sequences of elements of an array.
-+	 *
-+	 * @param x an array.
-+	 * @param a a position in {@code x}.
-+	 * @param b another position in {@code x}.
-+	 * @param n the number of elements to exchange starting at {@code a} and {@code b}.
-+	 */
-+ public static <K> void swap( final K[] x, int a, int b, final int n ) {
-+  for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
-+ }
-+ private static <K> int med3( final K x[], final int a, final int b, final int c, Comparator <K> comp ) {
-+  final int ab = comp.compare( x[ a ], x[ b ] );
-+  final int ac = comp.compare( x[ a ], x[ c ] );
-+  final int bc = comp.compare( x[ b ], x[ c ] );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static <K> void selectionSort( final K[] a, final int from, final int to, final Comparator <K> comp ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
-+   if ( m != i ) {
-+    final K u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+ private static <K> void insertionSort( final K[] a, final int from, final int to, final Comparator <K> comp ) {
-+  for ( int i = from; ++i < to; ) {
-+   K t = a[ i ];
-+   int j = i;
-+   for ( K u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static <K> void quickSort( final K[] x, final int from, final int to, final Comparator <K> comp ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to, comp );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s, comp );
-+   m = med3( x, m - s, m, m + s, comp );
-+   n = med3( x, n - 2 * s, n - s, n, comp );
-+  }
-+  m = med3( x, l, m, n, comp ); // Mid-size, med of 3
-+  final K v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while( true ) {
-+   int comparison;
-+   while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * 
-+	 */
-+ public static <K> void quickSort( final K[] x, final Comparator <K> comp ) {
-+  quickSort( x, 0, x.length, comp );
-+ }
-+ protected static class ForkJoinQuickSortComp <K> extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final K[] x;
-+  private final Comparator <K> comp;
-+  public ForkJoinQuickSortComp( final K[] x , final int from , final int to, final Comparator <K> comp ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.comp = comp;
-+  }
-+  @Override
-+  protected void compute() {
-+   final K[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to, comp );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final K v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp <K>( x, from, from + s, comp ), new ForkJoinQuickSortComp <K>( x, to - t, to, comp ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp <K>( x, from, from + s, comp ) );
-+   else invokeAll( new ForkJoinQuickSortComp <K>( x, to - t, to, comp ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x, final int from, final int to, final Comparator <K> comp ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortComp <K>( x, from, to, comp ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using a parallel quicksort. 
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x, final Comparator <K> comp ) {
-+  parallelQuickSort( x, 0, x.length, comp );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> int med3( final K x[], final int a, final int b, final int c ) {
-+  final int ab = ( ((Comparable<K>)(x[ a ])).compareTo(x[ b ]) );
-+  final int ac = ( ((Comparable<K>)(x[ a ])).compareTo(x[ c ]) );
-+  final int bc = ( ((Comparable<K>)(x[ b ])).compareTo(x[ c ]) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> void selectionSort( final K[] a, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i;
-+   for( int j = i + 1; j < to; j++ ) if ( ( ((Comparable<K>)(a[ j ])).compareTo(a[ m ]) < 0 ) ) m = j;
-+   if ( m != i ) {
-+    final K u = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = u;
-+   }
-+  }
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> void insertionSort( final K[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   K t = a[ i ];
-+   int j = i;
-+   for ( K u = a[ j - 1 ]; ( ((Comparable<K>)(t)).compareTo(u) < 0 ); u = a[ --j - 1 ] ) {
-+    a[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   a[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> void quickSort( final K[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, l, m, n ); // Mid-size, med of 3
-+  final K v = x[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) >=0 ) {
-+    if ( comparison == 0 ) swap( x, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static <K> void quickSort( final K[] x ) {
-+  quickSort( x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort <K> extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final K[] x;
-+  public ForkJoinQuickSort( final K[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+  }
-+  @Override
-+  @SuppressWarnings("unchecked")
-+  protected void compute() {
-+   final K[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, l, l + s, l + 2 * s );
-+   m = med3( x, m - s, m, m + s );
-+   n = med3( x, n - 2 * s, n - s, n );
-+   m = med3( x, l, m, n );
-+   final K v = x[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort <K>( x, from, from + s ), new ForkJoinQuickSort <K>( x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort <K>( x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort <K>( x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSort <K>( x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x ) {
-+  parallelQuickSort( x, 0, x.length );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> int med3Indirect( final int perm[], final K x[], final int a, final int b, final int c ) {
-+  final K aa = x[ perm[ a ] ];
-+  final K bb = x[ perm[ b ] ];
-+  final K cc = x[ perm[ c ] ];
-+  final int ab = ( ((Comparable<K>)(aa)).compareTo(bb) );
-+  final int ac = ( ((Comparable<K>)(aa)).compareTo(cc) );
-+  final int bc = ( ((Comparable<K>)(bb)).compareTo(cc) );
-+  return ( ab < 0 ?
-+   ( bc < 0 ? b : ac < 0 ? c : a ) :
-+   ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> void insertionSortIndirect( final int[] perm, final K[] a, final int from, final int to ) {
-+  for ( int i = from; ++i < to; ) {
-+   int t = perm[ i ];
-+   int j = i;
-+   for ( int u = perm[ j - 1 ]; ( ((Comparable<K>)(a[ t ])).compareTo(a[ u ]) < 0 ); u = perm[ --j - 1 ] ) {
-+    perm[ j ] = u;
-+    if ( from == j - 1 ) {
-+     --j;
-+     break;
-+    }
-+   }
-+   perm[ j ] = t;
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> void quickSortIndirect( final int[] perm, final K[] x, final int from, final int to ) {
-+  final int len = to - from;
-+  // Selection sort on smallest arrays
-+  if ( len < QUICKSORT_NO_REC ) {
-+   insertionSortIndirect( perm, x, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+  }
-+  m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
-+  final K v = x[ perm[ m ] ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while(true) {
-+   int comparison;
-+   while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+    b++;
-+   }
-+   while (c >= b && ( comparison = ( ((Comparable<K>)(x[ perm[ c ] ])).compareTo(v) ) ) >=0 ) {
-+    if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   IntArrays.swap( perm, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  IntArrays.swap( perm, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  IntArrays.swap( perm, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
-+ }
-+ /** Sorts an array according to the natural ascending order using indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>Note that this implementation does not allocate any object, contrarily to the implementation
-+	 * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 */
-+ public static <K> void quickSortIndirect( final int perm[], final K[] x ) {
-+  quickSortIndirect( perm, x, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSortIndirect <K> extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final int[] perm;
-+  private final K[] x;
-+  public ForkJoinQuickSortIndirect( final int perm[], final K[] x , final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.perm = perm;
-+  }
-+  @Override
-+  @SuppressWarnings("unchecked")
-+  protected void compute() {
-+   final K[] x = this.x;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSortIndirect( perm, x, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3Indirect( perm, x, l, l + s, l + 2 * s );
-+   m = med3Indirect( perm, x, m - s, m, m + s );
-+   n = med3Indirect( perm, x, n - 2 * s, n - s, n );
-+   m = med3Indirect( perm, x, l, m, n );
-+   final K v = x[ perm[ m ] ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison;
-+    while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( ((Comparable<K>)(x[ perm[ c ] ])).compareTo(v) ) ) >= 0 ) {
-+     if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    IntArrays.swap( perm, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   IntArrays.swap( perm, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   IntArrays.swap( perm, b, to - s, s );
-+   // Recursively sort non-partition-elements
-+   s = b - a;
-+   t = d - c;
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, from, from + s ), new ForkJoinQuickSortIndirect <K>( perm, x, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, to - t, to ) );
-+  }
-+ }
-+ /**  Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static <K> void parallelQuickSortIndirect( final int[] perm, final K[] x, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
-+  else {
-+   final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+   pool.invoke( new ForkJoinQuickSortIndirect <K>( perm, x, from, to ) );
-+   pool.shutdown();
-+  }
-+ }
-+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
-+	 * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
-+	 * <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param perm a permutation array indexing {@code x}.
-+	 * @param x the array to be sorted.
-+	 * 
-+	 */
-+ public static <K> void parallelQuickSortIndirect( final int perm[], final K[] x ) {
-+  parallelQuickSortIndirect( perm, x, 0, x.length );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 * @param from the index of the first element (inclusive) to be stabilized.
-+	 * @param to the index of the last element (exclusive) to be stabilized.
-+	 */
-+ public static <K> void stabilize( final int perm[], final K[] x, final int from, final int to ) {
-+  int curr = from;
-+  for( int i = from + 1; i < to; i++ ) {
-+   if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
-+    if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
-+    curr = i;
-+   }
-+  }
-+  if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
-+ }
-+ /** Stabilizes a permutation.
-+	 *
-+	 * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
-+	 * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
-+	 * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x}, 
-+	 * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
-+	 *
-+	 * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort, 
-+	 * as most stable sort algorithms require a support array.
-+	 *
-+	 * <p>More precisely, assuming that <code>x[ perm[ i ] ] &le; x[ perm[ i + 1 ] ]</code>, after
-+	 * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
-+	 * <code>perm[ i ] &le; perm[ i + 1 ]</code>.
-+	 *
-+	 * @param perm a permutation array indexing {@code x} so that it is sorted.
-+	 * @param x the sorted array to be stabilized.
-+	 */
-+ public static <K> void stabilize( final int perm[], final K[] x ) {
-+  stabilize( perm, x, 0, perm.length );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> int med3( final K x[], final K[] y, final int a, final int b, final int c ) {
-+  int t;
-+  final int ab = ( t = ( ((Comparable<K>)(x[ a ])).compareTo(x[ b ]) ) ) == 0 ? ( ((Comparable<K>)(y[ a ])).compareTo(y[ b ]) ) : t;
-+  final int ac = ( t = ( ((Comparable<K>)(x[ a ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable<K>)(y[ a ])).compareTo(y[ c ]) ) : t;
-+  final int bc = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(y[ c ]) ) : t;
-+  return ( ab < 0 ?
-+    ( bc < 0 ? b : ac < 0 ? c : a ) :
-+    ( bc > 0 ? b : ac > 0 ? c : a ) );
-+ }
-+ private static <K> void swap( final K x[], final K[] y, final int a, final int b ) {
-+  final K t = x[ a ];
-+  final K u = y[ a ];
-+  x[ a ] = x[ b ];
-+  y[ a ] = y[ b ];
-+  x[ b ] = t;
-+  y[ b ] = u;
-+ }
-+ private static <K> void swap( final K[] x, final K[] y, int a, int b, final int n ) {
-+  for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
-+ }
-+ @SuppressWarnings("unchecked")
-+ private static <K> void selectionSort( final K[] a, final K[] b, final int from, final int to ) {
-+  for( int i = from; i < to - 1; i++ ) {
-+   int m = i, u;
-+   for( int j = i + 1; j < to; j++ )
-+    if ( ( u = ( ((Comparable<K>)(a[ j ])).compareTo(a[ m ]) ) ) < 0 || u == 0 && ( ((Comparable<K>)(b[ j ])).compareTo(b[ m ]) < 0 ) ) m = j;
-+   if ( m != i ) {
-+    K t = a[ i ];
-+    a[ i ] = a[ m ];
-+    a[ m ] = t;
-+    t = b[ i ];
-+    b[ i ] = b[ m ];
-+    b[ m ] = t;
-+   }
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> void quickSort( final K[] x, final K[] y, final int from, final int to ) {
-+  final int len = to - from;
-+  if ( len < QUICKSORT_NO_REC ) {
-+   selectionSort( x, y, from, to );
-+   return;
-+  }
-+  // Choose a partition element, v
-+  int m = from + len / 2;
-+  int l = from;
-+  int n = to - 1;
-+  if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+  }
-+  m = med3( x, y, l, m, n ); // Mid-size, med of 3
-+  final K v = x[ m ], w = y[ m ];
-+  // Establish Invariant: v* (<v)* (>v)* v*
-+  int a = from, b = a, c = to - 1, d = c;
-+  while ( true ) {
-+   int comparison, t;
-+   while ( b <= c && ( comparison = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(w) ) : t ) <= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, a++, b );
-+    b++;
-+   }
-+   while ( c >= b && ( comparison = ( t = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ c ])).compareTo(w) ) : t ) >= 0 ) {
-+    if ( comparison == 0 ) swap( x, y, c, d-- );
-+    c--;
-+   }
-+   if ( b > c ) break;
-+   swap( x, y, b++, c-- );
-+  }
-+  // Swap partition elements back to middle
-+  int s;
-+  s = Math.min( a - from, b - a );
-+  swap( x, y, from, b - s, s );
-+  s = Math.min( d - c, to - d - 1 );
-+  swap( x, y, b, to - s, s );
-+  // Recursively sort non-partition-elements
-+  if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
-+  if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
-+ }
-+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+     *
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static <K> void quickSort( final K[] x, final K[] y ) {
-+  ensureSameLength( x, y );
-+  quickSort( x, y, 0, x.length );
-+ }
-+ protected static class ForkJoinQuickSort2 <K> extends RecursiveAction {
-+  private static final long serialVersionUID = 1L;
-+  private final int from;
-+  private final int to;
-+  private final K[] x, y;
-+  public ForkJoinQuickSort2( final K[] x, final K[] y, final int from , final int to ) {
-+   this.from = from;
-+   this.to = to;
-+   this.x = x;
-+   this.y = y;
-+  }
-+  @Override
-+  @SuppressWarnings("unchecked")
-+  protected void compute() {
-+   final K[] x = this.x;
-+   final K[] y = this.y;
-+   final int len = to - from;
-+   if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
-+    quickSort( x, y, from, to );
-+    return;
-+   }
-+   // Choose a partition element, v
-+   int m = from + len / 2;
-+   int l = from;
-+   int n = to - 1;
-+   int s = len / 8;
-+   l = med3( x, y, l, l + s, l + 2 * s );
-+   m = med3( x, y, m - s, m, m + s );
-+   n = med3( x, y, n - 2 * s, n - s, n );
-+   m = med3( x, y, l, m, n );
-+   final K v = x[ m ], w = y[ m ];
-+   // Establish Invariant: v* (<v)* (>v)* v*
-+   int a = from, b = a, c = to - 1, d = c;
-+   while ( true ) {
-+    int comparison, t;
-+    while ( b <= c && ( comparison = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(w) ) : t ) <= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, a++, b );
-+     b++;
-+    }
-+    while ( c >= b && ( comparison = ( t = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ c ])).compareTo(w) ) : t ) >= 0 ) {
-+     if ( comparison == 0 ) swap( x, y, c, d-- );
-+     c--;
-+    }
-+    if ( b > c ) break;
-+    swap( x, y, b++, c-- );
-+   }
-+   // Swap partition elements back to middle
-+   int t;
-+   s = Math.min( a - from, b - a );
-+   swap( x, y, from, b - s, s );
-+   s = Math.min( d - c, to - d - 1 );
-+   swap( x, y, b, to - s, s );
-+   s = b - a;
-+   t = d - c;
-+   // Recursively sort non-partition-elements
-+   if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 <K>( x, y, from, from + s ), new ForkJoinQuickSort2 <K>( x, y, to - t, to ) );
-+   else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 <K>( x, y, from, from + s ) );
-+   else invokeAll( new ForkJoinQuickSort2 <K>( x, y, to - t, to ) );
-+  }
-+ }
-+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x, final K[] y, final int from, final int to ) {
-+  if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
-+  final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
-+  pool.invoke( new ForkJoinQuickSort2 <K>( x, y, from, to ) );
-+  pool.shutdown();
-+ }
-+ /** Sorts two arrays according to the natural lexicographical 
-+	 *  ascending order using a parallel quicksort.
-+	 * 
-+	 * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
-+	 * McIlroy, &ldquo;Engineering a Sort Function&rdquo;, <i>Software: Practice and Experience</i>, 23(11), pages
-+	 * 1249&minus;1265, 1993.
-+	 * 
-+	 * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
-+	 * elements in the same position in the two provided arrays will be considered a single key, and
-+	 * permuted accordingly. In the end, either <code>x[ i ] &lt; x[ i + 1 ]</code> or <code>x[ i ]
-+	 * == x[ i + 1 ]</code> and <code>y[ i ] &le; y[ i + 1 ]</code>.
-+	 *
-+	 * <p>This implementation uses a {@link ForkJoinPool} executor service with
-+	 * {@link Runtime#availableProcessors()} parallel threads.
-+	 * 
-+	 * @param x the first array to be sorted.
-+	 * @param y the second array to be sorted.
-+	 */
-+ public static <K> void parallelQuickSort( final K[] x, final K[] y ) {
-+  ensureSameLength( x, y );
-+  parallelQuickSort( x, y, 0, x.length );
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated. 
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> void mergeSort( final K a[], final int from, final int to, final K supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to );
-+   return;
-+  }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, a );
-+  mergeSort( supp, mid, to, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( ( ((Comparable<K>)(supp[ mid - 1 ])).compareTo(supp[ mid ]) <= 0 ) ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && ( ((Comparable<K>)(supp[ p ])).compareTo(supp[ q ]) <= 0 ) ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 */
-+ public static <K> void mergeSort( final K a[], final int from, final int to ) {
-+  mergeSort( a, from, to, a.clone() );
-+ }
-+ /**	Sorts an array according to the natural ascending order using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 */
-+ public static <K> void mergeSort( final K a[] ) {
-+  mergeSort( a, 0, a.length );
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort, using a given pre-filled support array.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. Moreover, no support arrays will be allocated.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
-+	 * of {@code a} in the specified range.
-+	 */
-+ public static <K> void mergeSort( final K a[], final int from, final int to, Comparator <K> comp, final K supp[] ) {
-+  int len = to - from;
-+  // Insertion sort on smallest arrays
-+  if ( len < MERGESORT_NO_REC ) {
-+   insertionSort( a, from, to, comp );
-+   return;
-+     }
-+  // Recursively sort halves of a into supp
-+  final int mid = ( from + to ) >>> 1;
-+  mergeSort( supp, from, mid, comp, a );
-+  mergeSort( supp, mid, to, comp, a );
-+  // If list is already sorted, just copy from supp to a.  This is an
-+  // optimization that results in faster sorts for nearly ordered lists.
-+  if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
-+   System.arraycopy( supp, from, a, from, len );
-+   return;
-+  }
-+  // Merge sorted halves (now in supp) into a
-+  for( int i = from, p = from, q = mid; i < to; i++ ) {
-+   if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
-+   else a[ i ] = supp[ q++ ];
-+  }
-+ }
-+ /** Sorts the specified range of elements according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort. An array as large as <code>a</code> will be allocated by this method.
-+	 *
-+	 * @param a the array to be sorted.
-+	 * @param from the index of the first element (inclusive) to be sorted.
-+	 * @param to the index of the last element (exclusive) to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static <K> void mergeSort( final K a[], final int from, final int to, Comparator <K> comp ) {
-+  mergeSort( a, from, to, comp, a.clone() );
-+ }
-+ /** Sorts an array according to the order induced by the specified
-+	 * comparator using mergesort.
-+	 * 
-+	 * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
-+	 * of the sort.  An array as large as <code>a</code> will be allocated by this method.
-+	 
-+	 * @param a the array to be sorted.
-+	 * @param comp the comparator to determine the sorting order.
-+	 */
-+ public static <K> void mergeSort( final K a[], Comparator <K> comp ) {
-+  mergeSort( a, 0, a.length, comp );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> int binarySearch( final K[] a, int from, int to, final K key ) {
-+  K midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   final int cmp = ((Comparable <? super K>)midVal).compareTo( key );
-+   if ( cmp < 0 ) from = mid + 1;
-+   else if (cmp > 0) to = mid - 1;
-+   else return mid;
-+        }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm. The range must be sorted prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static <K> int binarySearch( final K[] a, final K key ) {
-+  return binarySearch( a, 0, a.length, key );
-+ }
-+ /**
-+	 * Searches a range of the specified array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param from  the index of the first element (inclusive) to be searched.
-+	 * @param to  the index of the last element (exclusive) to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static <K> int binarySearch( final K[] a, int from, int to, final K key, final Comparator <K> c ) {
-+  K midVal;
-+  to--;
-+  while (from <= to) {
-+   final int mid = (from + to) >>> 1;
-+   midVal = a[ mid ];
-+   final int cmp = c.compare( midVal, key );
-+   if ( cmp < 0 ) from = mid + 1;
-+   else if (cmp > 0) to = mid - 1;
-+   else return mid; // key found
-+  }
-+  return -( from + 1 );
-+ }
-+ /**
-+	 * Searches an array for the specified value using 
-+	 * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call. 
-+	 * If it is not sorted, the results are undefined. If the range contains multiple elements with 
-+	 * the specified value, there is no guarantee which one will be found.
-+	 *
-+	 * @param a the array to be searched.
-+	 * @param key the value to be searched for.
-+	 * @param c a comparator.
-+	 * @return index of the search key, if it is contained in the array;
-+	 *             otherwise, <code>(-(<i>insertion point</i>) - 1)</code>.  The <i>insertion
-+	 *             point</i> is defined as the the point at which the value would
-+	 *             be inserted into the array: the index of the first
-+	 *             element greater than the key, or the length of the array, if all
-+	 *             elements in the array are less than the specified key.  Note
-+	 *             that this guarantees that the return value will be &ge; 0 if
-+	 *             and only if the key is found.
-+	 * @see java.util.Arrays
-+	 */
-+ public static <K> int binarySearch( final K[] a, final K key, final Comparator <K> c ) {
-+  return binarySearch( a, 0, a.length, key, c );
-+ }
-+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param from the index of the first element (inclusive) to be shuffled.
-+	 * @param to the index of the last element (exclusive) to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static <K> K[] shuffle( final K[] a, final int from, final int to, final Random random ) {
-+  for( int i = to - from; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final K t = a[ from + i ];
-+   a[ from + i ] = a[ from + p ];
-+   a[ from + p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Shuffles the specified array using the specified pseudorandom number generator.
-+	 * 
-+	 * @param a the array to be shuffled.
-+	 * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
-+	 * @return <code>a</code>.
-+	 */
-+ public static <K> K[] shuffle( final K[] a, final Random random ) {
-+  for( int i = a.length; i-- != 0; ) {
-+   final int p = random.nextInt( i + 1 );
-+   final K t = a[ i ];
-+   a[ i ] = a[ p ];
-+   a[ p ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static <K> K[] reverse( final K[] a ) {
-+  final int length = a.length;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final K t = a[ length - i - 1 ];
-+   a[ length - i - 1 ] = a[ i ];
-+   a[ i ] = t;
-+  }
-+  return a;
-+ }
-+ /** Reverses the order of the elements in the specified array fragment.
-+	 * 
-+	 * @param a the array to be reversed.
-+	 * @param from the index of the first element (inclusive) to be reversed.
-+	 * @param to the index of the last element (exclusive) to be reversed.
-+	 * @return <code>a</code>.
-+	 */
-+ public static <K> K[] reverse( final K[] a, final int from, final int to ) {
-+  final int length = to - from;
-+  for( int i = length / 2; i-- != 0; ) {
-+   final K t = a[ from + length - i - 1 ];
-+   a[ from + length - i - 1 ] = a[ from + i ];
-+   a[ from + i ] = t;
-+  }
-+  return a;
-+ }
-+ /** A type-specific content-based hash strategy for arrays. */
-+ private static final class ArrayHashStrategy <K> implements Hash.Strategy<K[]>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  public int hashCode( final K[] o ) {
-+   return java.util.Arrays.hashCode( o );
-+  }
-+  public boolean equals( final K[] a, final K[] b ) {
-+   return java.util.Arrays.equals( a, b );
-+  }
-+ }
-+ /** A type-specific content-based hash strategy for arrays.
-+	 *
-+	 * <P>This hash strategy may be used in custom hash collections whenever keys are
-+	 * arrays, and they must be considered equal by content. This strategy
-+	 * will handle <code>null</code> correctly, and it is serializable.
-+	 */
-+ @SuppressWarnings({"rawtypes"})
-+ public final static Hash.Strategy HASH_STRATEGY = new ArrayHashStrategy();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import it.unimi.dsi.fastutil.BidirectionalIterator;
-+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
-+ * and the possibility to skip elements backwards.
-+ *
-+ * @see BidirectionalIterator
-+ */
-+public interface ObjectBidirectionalIterator <K> extends ObjectIterator <K>, BidirectionalIterator<K> {
-+ /** Moves back for the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #previous()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasPrevious()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip back.
-+	 * @return the number of elements actually skipped.
-+	 * @see java.util.Iterator#next()
-+	 */
-+ int back( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Collection;
-+/** A type-specific {@link Collection}; provides some additional methods
-+ * that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
-+ * a slightly different semantics for {@link #toArray(Object[])}.
-+ *
-+ * @see Collection
-+ */
-+public interface ObjectCollection <K> extends Collection<K>, ObjectIterable <K> {
-+ /** Returns a type-specific iterator on the elements of this collection.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in 
-+	 * {@link java.lang.Iterable#iterator()}, which was already 
-+	 * strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Collection}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this collection.
-+	 */
-+ ObjectIterator <K> iterator();
-+ /** Returns a type-specific iterator on this elements of this collection.
-+	 *
-+	 * @see #iterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ ObjectIterator <K> objectIterator();
-+ /** Returns an containing the items of this collection;
-+	 * the runtime type of the returned array is that of the specified array. 
-+	 *
-+	 * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
-+	 * methods just writes all elements of this collection: no special 
-+	 * value will be added after the last one.
-+	 *
-+	 * @param a if this array is big enough, it will be used to store this collection.
-+	 * @return a primitive type array containing the items of this collection.
-+	 * @see Collection#toArray(Object[])
-+	 */
-+ <T> T[] toArray(T[] a);
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Collection;
-+import it.unimi.dsi.fastutil.objects.ObjectArrays;
-+/** A class providing static methods and objects that do useful things with type-specific collections.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class ObjectCollections {
-+ private ObjectCollections() {}
-+ /** An immutable class representing an empty type-specific collection.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific collection.
-+	 */
-+ public abstract static class EmptyCollection <K> extends AbstractObjectCollection <K> {
-+  protected EmptyCollection() {}
-+  public boolean add( K k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( Object k ) { return false; }
-+  public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
-+  public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  public <T> T[] toArray( T[] a ) { return a; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.EMPTY_ITERATOR; }
-+  public int size() { return 0; }
-+  public void clear() {}
-+  public int hashCode() { return 0; }
-+  public boolean equals( Object o ) {
-+   if ( o == this ) return true;
-+   if ( ! ( o instanceof Collection ) ) return false;
-+   return ((Collection<?>)o).isEmpty();
-+  }
-+ }
-+ /** A synchronized wrapper class for collections. */
-+ public static class SynchronizedCollection <K> implements ObjectCollection <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final ObjectCollection <K> collection;
-+  protected final Object sync;
-+  protected SynchronizedCollection( final ObjectCollection <K> c, final Object sync ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = sync;
-+  }
-+  protected SynchronizedCollection( final ObjectCollection <K> c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+   this.sync = this;
-+  }
-+  public int size() { synchronized( sync ) { return collection.size(); } }
-+  public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
-+  public boolean contains( final Object o ) { synchronized( sync ) { return collection.contains( o ); } }
-+  public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
-+  public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
-+  public ObjectIterator <K> iterator() { return collection.iterator(); }
-+  @Deprecated
-+  public ObjectIterator <K> objectIterator() { return iterator(); }
-+  public boolean add( final K k ) { synchronized( sync ) { return collection.add( k ); } }
-+  public boolean rem( final Object k ) { synchronized( sync ) { return collection.remove( k ); } }
-+  public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
-+  public boolean addAll( final Collection<? extends K> c ) { synchronized( sync ) { return collection.addAll( c ); } }
-+  public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
-+  public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
-+  public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
-+  public void clear() { synchronized( sync ) { collection.clear(); } }
-+  public String toString() { synchronized( sync ) { return collection.toString(); } }
-+ }
-+ /** Returns a synchronized collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c ) { return new SynchronizedCollection <K>( c ); }
-+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
-+	 *
-+	 * @param c the collection to be wrapped in a synchronized collection.
-+	 * @param sync an object that will be used to synchronize the list access.
-+	 * @return a synchronized view of the specified collection.
-+	 * @see java.util.Collections#synchronizedCollection(Collection)
-+	 */
-+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c, final Object sync ) { return new SynchronizedCollection <K>( c, sync ); }
-+ /** An unmodifiable wrapper class for collections. */
-+ public static class UnmodifiableCollection <K> implements ObjectCollection <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final ObjectCollection <K> collection;
-+  protected UnmodifiableCollection( final ObjectCollection <K> c ) {
-+   if ( c == null ) throw new NullPointerException();
-+   this.collection = c;
-+  }
-+  public int size() { return collection.size(); }
-+  public boolean isEmpty() { return collection.isEmpty(); }
-+  public boolean contains( final Object o ) { return collection.contains( o ); }
-+  public ObjectIterator <K> iterator() { return ObjectIterators.unmodifiable( collection.iterator() ); }
-+  @Deprecated
-+  public ObjectIterator <K> objectIterator() { return iterator(); }
-+  public boolean add( final K k ) { throw new UnsupportedOperationException(); }
-+  public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
-+  public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
-+  public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public void clear() { throw new UnsupportedOperationException(); }
-+  public String toString() { return collection.toString(); }
-+  public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
-+  public Object[] toArray() { return collection.toArray(); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified collection.
-+	 *
-+	 * @param c the collection to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable view of the specified collection.
-+	 * @see java.util.Collections#unmodifiableCollection(Collection)
-+	 */
-+ public static <K> ObjectCollection <K> unmodifiable( final ObjectCollection <K> c ) { return new UnmodifiableCollection <K>( c ); }
-+ /** A collection wrapper class for iterables. */
-+ public static class IterableCollection <K> extends AbstractObjectCollection <K> implements java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final ObjectIterable <K> iterable;
-+  protected IterableCollection( final ObjectIterable <K> iterable ) {
-+   if ( iterable == null ) throw new NullPointerException();
-+   this.iterable = iterable;
-+  }
-+  public int size() {
-+   int c = 0;
-+   final ObjectIterator <K> iterator = iterator();
-+   while( iterator.hasNext() ) {
-+    iterator.next();
-+    c++;
-+   }
-+   return c;
-+  }
-+  public boolean isEmpty() { return iterable.iterator().hasNext(); }
-+  public ObjectIterator <K> iterator() { return iterable.iterator(); }
-+  @Deprecated
-+  public ObjectIterator <K> objectIterator() { return iterator(); }
-+ }
-+ /** Returns an unmodifiable collection backed by the specified iterable.
-+	 *
-+	 * @param iterable the iterable object to be wrapped in an unmodifiable collection.
-+	 * @return an unmodifiable collection view of the specified iterable.
-+	 */
-+ public static <K> ObjectCollection <K> asCollection( final ObjectIterable <K> iterable ) {
-+  if ( iterable instanceof ObjectCollection ) return (ObjectCollection <K>)iterable;
-+  return new IterableCollection <K>( iterable );
-+ }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.lang.Iterable;
-+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
-+ *
-+ * <p><strong>Warning</strong>: Java will let you write &ldquo;colon&rdquo; <code>for</code> statements with primitive-type
-+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
-+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
-+ *
-+ * @see Iterable
-+ */
-+public interface ObjectIterable <K> extends Iterable<K> {
-+ /** Returns a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
-+	 *
-+	 * @return a type-specific iterator.
-+	 */
-+ ObjectIterator <K> iterator();
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Iterator;
-+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
-+ * the possibility to skip elements.
-+ *
-+ * @see Iterator
-+ */
-+public interface ObjectIterator <K> extends Iterator<K> {
-+ /** Skips the given number of elements.
-+	 *
-+	 * <P>The effect of this call is exactly the same as that of
-+	 * calling {@link #next()} for <code>n</code> times (possibly stopping
-+	 * if {@link #hasNext()} becomes false).
-+	 *
-+	 * @param n the number of elements to skip.
-+	 * @return the number of elements actually skipped.
-+	 * @see Iterator#next()
-+	 */
-+ int skip( int n );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Iterator;
-+import java.util.ListIterator;
-+import java.util.NoSuchElementException;
-+/** A class providing static methods and objects that do useful things with type-specific iterators.
-+ *
-+ * @see Iterator
-+ */
-+public class ObjectIterators {
-+ private ObjectIterators() {}
-+ /** A class returning no elements and a type-specific iterator interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific iterator.
-+	 */
-+ public static class EmptyIterator <K> extends AbstractObjectListIterator <K> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptyIterator() {}
-+  public boolean hasNext() { return false; }
-+  public boolean hasPrevious() { return false; }
-+  public K next() { throw new NoSuchElementException(); }
-+  public K previous() { throw new NoSuchElementException(); }
-+  public int nextIndex() { return 0; }
-+  public int previousIndex() { return -1; }
-+  public int skip( int n ) { return 0; };
-+  public int back( int n ) { return 0; };
-+  public Object clone() { return EMPTY_ITERATOR; }
-+        private Object readResolve() { return EMPTY_ITERATOR; }
-+ }
-+ /** An empty iterator (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>The class of this objects represent an abstract empty iterator
-+	 * that can iterate as a type-specific (list) iterator.
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
-+ /** An iterator returning a single element. */
-+ private static class SingletonIterator <K> extends AbstractObjectListIterator <K> {
-+  private final K element;
-+  private int curr;
-+  public SingletonIterator( final K element ) {
-+   this.element = element;
-+  }
-+  public boolean hasNext() { return curr == 0; }
-+  public boolean hasPrevious() { return curr == 1; }
-+  public K next() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   curr = 1;
-+   return element;
-+  }
-+  public K previous() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   curr = 0;
-+   return element;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Returns an iterator that iterates just over the given element.
-+	 *
-+	 * @param element the only element to be returned by a type-specific list iterator.
-+	 * @return  an iterator that iterates just over <code>element</code>.
-+	 */
-+ public static <K> ObjectListIterator <K> singleton( final K element ) {
-+  return new SingletonIterator <K>( element );
-+ }
-+ /** A class to wrap arrays in iterators. */
-+ private static class ArrayIterator <K> extends AbstractObjectListIterator <K> {
-+  private final K[] array;
-+  private final int offset, length;
-+  private int curr;
-+  public ArrayIterator( final K[] array, final int offset, final int length ) {
-+   this.array = array;
-+   this.offset = offset;
-+   this.length = length;
-+  }
-+  public boolean hasNext() { return curr < length; }
-+  public boolean hasPrevious() { return curr > 0; }
-+  public K next() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   return array[ offset + curr++ ];
-+  }
-+  public K previous() {
-+   if ( ! hasPrevious() ) throw new NoSuchElementException();
-+   return array[ offset + --curr ];
-+  }
-+  public int skip( int n ) {
-+   if ( n <= length - curr ) {
-+    curr += n;
-+    return n;
-+   }
-+   n = length - curr;
-+   curr = length;
-+   return n;
-+  }
-+  public int back( int n ) {
-+   if ( n <= curr ) {
-+    curr -= n;
-+    return n;
-+   }
-+   n = curr;
-+   curr = 0;
-+   return n;
-+  }
-+  public int nextIndex() {
-+   return curr;
-+  }
-+  public int previousIndex() {
-+   return curr - 1;
-+  }
-+ }
-+ /** Wraps the given part of an array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will iterate
-+	 * <code>length</code> times, returning consecutive elements of the given
-+	 * array starting from the one with index <code>offset</code>.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param length the number of elements to return.
-+	 * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
-+	 */
-+ public static <K> ObjectListIterator <K> wrap( final K[] array, final int offset, final int length ) {
-+  ObjectArrays.ensureOffsetLength( array, offset, length );
-+  return new ArrayIterator <K>( array, offset, length );
-+ }
-+ /** Wraps the given array into a type-specific list iterator.
-+	 *
-+	 * <P>The type-specific list iterator returned by this method will return
-+	 * all elements of the given array.
-+	 *
-+	 * @param array an array to wrap into a type-specific list iterator.
-+	 * @return an iterator that will the elements of <code>array</code>.
-+	 */
-+ public static <K> ObjectListIterator <K> wrap( final K[] array ) {
-+  return new ArrayIterator <K>( array, 0, array.length );
-+ }
-+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @param offset the first element of the array to be returned.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[], int offset, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.next();
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given array. The iteration will stop when the
-+	 * iterator has no more elements or when the end of the array has been reached.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param array an array to contain the output of the iterator.
-+	 * @return the number of elements unwrapped.
-+	 */
-+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[] ) {
-+  return unwrap( i, array, 0, array.length );
-+ }
-+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator. At most <code>max</code> elements
-+	 * will be returned.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be unwrapped.
-+	 * @return an array containing the elements returned by the iterator (at most <code>max</code>).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> K[] unwrap( final Iterator <? extends K> i, int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  K array[] = (K[]) new Object[ 16 ];
-+  int j = 0;
-+  while( max-- != 0 && i.hasNext() ) {
-+   if ( j == array.length ) array = ObjectArrays.grow( array, j + 1 );
-+   array[ j++ ] = i.next();
-+  }
-+  return ObjectArrays.trim( array, j );
-+ }
-+ /** Unwraps an iterator, returning an array.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns an array
-+	 * containing the elements returned by the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return an array containing the elements returned by the iterator.
-+	 */
-+ public static <K> K[] unwrap( final Iterator <? extends K> i ) {
-+  return unwrap( i, Integer.MAX_VALUE );
-+ }
-+ /** Unwraps an iterator into a type-specific collection,  with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the elements
-+	 * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
-+	 * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
-+	 * the iterator emits less than <code>max</code> elements).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection array to contain the output of the iterator.
-+	 * @param max the maximum number of elements to unwrap.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static <K> int unwrap( final Iterator <K> i, final ObjectCollection <? super K> c, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) c.add( i.next() );
-+  return max - j - 1;
-+ }
-+ /** Unwraps an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and stores the
-+	 * elements returned in the given type-specific collection. The returned count on the number
-+	 * unwrapped elements is a long, so that it will work also with very large collections.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param c a type-specific collection to contain the output of the iterator.
-+	 * @return the number of elements unwrapped. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static <K> long unwrap( final Iterator <K> i, final ObjectCollection <? super K> c ) {
-+  long n = 0;
-+  while( i.hasNext() ) {
-+   c.add( i.next() );
-+   n++;
-+  }
-+  return n;
-+ }
-+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection (up to <code>max</code>).
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s, final int max ) {
-+  if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
-+  int j = max;
-+  while( j-- != 0 && i.hasNext() ) s.add( i.next() );
-+  return max - j - 1;
-+ }
-+ /** Pours an iterator into a type-specific collection.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and adds
-+	 * the returned elements to the given collection.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param s a type-specific collection.
-+	 * @return the number of elements poured. Note that
-+	 * this is the number of elements returned by the iterator, which is not necessarily the number
-+	 * of elements that have been added to the collection (because of duplicates).
-+	 */
-+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s ) {
-+  return pour( i, s, Integer.MAX_VALUE );
-+ }
-+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @param max the maximum number of elements to be poured.
-+	 * @return a type-specific list containing the returned elements, up to <code>max</code>.
-+	 */
-+ public static <K> ObjectList <K> pour( final Iterator <K> i, int max ) {
-+  final ObjectArrayList <K> l = new ObjectArrayList <K>();
-+  pour( i, l, max );
-+  l.trim();
-+  return l;
-+ }
-+ /** Pours an iterator, returning a type-specific list.
-+	 *
-+	 * <P>This method iterates over the given type-specific iterator and returns
-+	 * a list containing the returned elements. Iteration
-+	 * on the returned list is guaranteed to produce the elements in the same order
-+	 * in which they appeared in the iterator.
-+	 *
-+	 * @param i a type-specific iterator.
-+	 * @return a type-specific list containing the returned elements.
-+	 */
-+ public static <K> ObjectList <K> pour( final Iterator <K> i ) {
-+  return pour( i, Integer.MAX_VALUE );
-+ }
-+ private static class IteratorWrapper <K> extends AbstractObjectIterator <K> {
-+  final Iterator<K> i;
-+  public IteratorWrapper( final Iterator<K> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public void remove() { i.remove(); }
-+  public K next() { return (i.next()); }
-+ }
-+ /** Wraps a standard iterator into a type-specific iterator.
-+	 *
-+	 * <P>This method wraps a standard iterator into a type-specific one which will handle the
-+	 * type conversions for you. Of course, any attempt to wrap an iterator returning the
-+	 * instances of the wrong class will generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i an iterator.
-+	 * @return a type-specific iterator  backed by <code>i</code>.
-+	 */
-+  public static <K> ObjectIterator <K> asObjectIterator( final Iterator <K> i ) {
-+  if ( i instanceof ObjectIterator ) return (ObjectIterator <K>)i;
-+  return new IteratorWrapper <K>( i );
-+ }
-+ private static class ListIteratorWrapper <K> extends AbstractObjectListIterator <K> {
-+  final ListIterator<K> i;
-+  public ListIteratorWrapper( final ListIterator<K> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+  public void set( K k ) { i.set( (k) ); }
-+  public void add( K k ) { i.add( (k) ); }
-+  public void remove() { i.remove(); }
-+  public K next() { return (i.next()); }
-+  public K previous() { return (i.previous()); }
-+ }
-+ /** Wraps a standard list iterator into a type-specific list iterator.
-+	 *
-+	 * <P>This method wraps a standard list iterator into a type-specific one
-+	 * which will handle the type conversions for you. Of course, any attempt
-+	 * to wrap an iterator returning the instances of the wrong class will
-+	 * generate a {@link ClassCastException}. The
-+	 * returned iterator is backed by <code>i</code>: changes to one of the iterators
-+	 * will affect the other, too.
-+	 *
-+	 * <P>If <code>i</code> is already type-specific, it will returned and no new object
-+	 * will be generated.
-+	 *
-+	 * @param i a list iterator.
-+	 * @return a type-specific list iterator backed by <code>i</code>.
-+	 */
-+  public static <K> ObjectListIterator <K> asObjectIterator( final ListIterator <K> i ) {
-+  if ( i instanceof ObjectListIterator ) return (ObjectListIterator <K>)i;
-+  return new ListIteratorWrapper <K>( i );
-+ }
-+ private static class IteratorConcatenator <K> extends AbstractObjectIterator <K> {
-+  final ObjectIterator <? extends K> a[];
-+  int offset, length, lastOffset = -1;
-+  public IteratorConcatenator( final ObjectIterator <? extends K> a[], int offset, int length ) {
-+   this.a = a;
-+   this.offset = offset;
-+   this.length = length;
-+   advance();
-+  }
-+  private void advance() {
-+   while( length != 0 ) {
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return;
-+  }
-+  public boolean hasNext() {
-+   return length > 0;
-+  }
-+  public K next() {
-+   if ( ! hasNext() ) throw new NoSuchElementException();
-+   K next = a[ lastOffset = offset ].next();
-+   advance();
-+   return next;
-+  }
-+  public void remove() {
-+   if ( lastOffset == -1 ) throw new IllegalStateException();
-+   a[ lastOffset ].remove();
-+  }
-+  public int skip( int n ) {
-+   lastOffset = -1;
-+   int skipped = 0;
-+   while( skipped < n && length != 0 ) {
-+    skipped += a[ offset ].skip( n - skipped );
-+    if ( a[ offset ].hasNext() ) break;
-+    length--;
-+    offset++;
-+   }
-+   return skipped;
-+  }
-+ }
-+ /** Concatenates all iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by all iterators contained in the given array.
-+	 *
-+	 * @param a an array of iterators.
-+	 * @return an iterator obtained by concatenation.
-+	 */
-+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[] ) {
-+  return concat( a, 0, a.length );
-+ }
-+ /** Concatenates a sequence of iterators contained in an array.
-+	 *
-+	 * <P>This method returns an iterator that will enumerate in order the elements returned
-+	 * by <code>a[ offset ]</code>, then those returned 
-+	 * by <code>a[ offset + 1 ]</code>, and so on up to 
-+	 * <code>a[ offset + length - 1 ]</code>. 
-+	 *
-+	 * @param a an array of iterators.
-+	 * @param offset the index of the first iterator to concatenate.
-+	 * @param length the number of iterators to concatenate.
-+	 * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
-+	 */
-+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[], final int offset, final int length ) {
-+  return new IteratorConcatenator <K>( a, offset, length );
-+ }
-+   /** An unmodifiable wrapper class for iterators. */
-+ public static class UnmodifiableIterator <K> extends AbstractObjectIterator <K> {
-+  final protected ObjectIterator <K> i;
-+  public UnmodifiableIterator( final ObjectIterator <K> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public K next() { return i.next(); }
-+ }
-+ /** Returns an unmodifiable iterator backed by the specified iterator.
-+	 *
-+	 * @param i the iterator to be wrapped in an unmodifiable iterator.
-+	 * @return an unmodifiable view of the specified iterator.
-+	 */
-+ public static <K> ObjectIterator <K> unmodifiable( final ObjectIterator <K> i ) { return new UnmodifiableIterator <K>( i ); }
-+   /** An unmodifiable wrapper class for bidirectional iterators. */
-+ public static class UnmodifiableBidirectionalIterator <K> extends AbstractObjectBidirectionalIterator <K> {
-+  final protected ObjectBidirectionalIterator <K> i;
-+  public UnmodifiableBidirectionalIterator( final ObjectBidirectionalIterator <K> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public K next() { return i.next(); }
-+  public K previous() { return i.previous(); }
-+ }
-+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
-+	 *
-+	 * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
-+	 * @return an unmodifiable view of the specified bidirectional iterator.
-+	 */
-+ public static <K> ObjectBidirectionalIterator <K> unmodifiable( final ObjectBidirectionalIterator <K> i ) { return new UnmodifiableBidirectionalIterator <K>( i ); }
-+   /** An unmodifiable wrapper class for list iterators. */
-+ public static class UnmodifiableListIterator <K> extends AbstractObjectListIterator <K> {
-+  final protected ObjectListIterator <K> i;
-+  public UnmodifiableListIterator( final ObjectListIterator <K> i ) {
-+   this.i = i;
-+  }
-+  public boolean hasNext() { return i.hasNext(); }
-+  public boolean hasPrevious() { return i.hasPrevious(); }
-+  public K next() { return i.next(); }
-+  public K previous() { return i.previous(); }
-+  public int nextIndex() { return i.nextIndex(); }
-+  public int previousIndex() { return i.previousIndex(); }
-+ }
-+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
-+	 *
-+	 * @param i the list iterator to be wrapped in an unmodifiable list iterator.
-+	 * @return an unmodifiable view of the specified list iterator.
-+	 */
-+ public static <K> ObjectListIterator <K> unmodifiable( final ObjectListIterator <K> i ) { return new UnmodifiableListIterator <K>( i ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.List;
-+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
-+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
-+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #listIterator()},
-+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
-+ *
-+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
-+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
-+ * of these methods, it is expected that concrete implementation override them with optimized versions.
-+ *
-+ * @see List
-+ */
-+public interface ObjectList <K> extends List<K>, Comparable<List<? extends K>>, ObjectCollection <K> {
-+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
-+	 *
-+	 * Note that this specification strengthens the one given in {@link List#iterator()}.
-+	 * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
-+	 * in {@link List}.
-+	 *
-+	 * @return an iterator on the elements of this list (in proper sequence).
-+	 */
-+ ObjectListIterator <K> iterator();
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see #listIterator()
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
-+	 */
-+ @Deprecated
-+ ObjectListIterator <K> objectListIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see #listIterator(int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
-+	 */
-+ @Deprecated
-+ ObjectListIterator <K> objectListIterator( int index );
-+ /** Returns a type-specific list iterator on the list.
-+	 *
-+	 * @see List#listIterator()
-+	 */
-+ ObjectListIterator <K> listIterator();
-+ /** Returns a type-specific list iterator on the list starting at a given index.
-+	 *
-+	 * @see List#listIterator(int)
-+	 */
-+ ObjectListIterator <K> listIterator( int index );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 * @see List#subList(int,int)
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
-+	 */
-+ @Deprecated
-+ ObjectList <K> objectSubList( int from, int to );
-+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
-+	 *
-+	 * @see List#subList(int,int)
-+	 */
-+ ObjectList <K> subList(int from, int to);
-+ /** Sets the size of this list.
-+	 *
-+	 * <P>If the specified size is smaller than the current size, the last elements are
-+	 * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
-+	 *
-+	 * @param size the new size.
-+	 */
-+ void size( int size );
-+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param a the destination array.
-+	 * @param offset the offset into the destination array where to store the first element copied.
-+	 * @param length the number of elements to be copied.
-+	 */
-+ void getElements( int from, Object a[], int offset, int length );
-+ /** Removes (hopefully quickly) elements of this type-specific list.
-+	 *
-+	 * @param from the start index (inclusive).
-+	 * @param to the end index (exclusive).
-+	 */
-+ void removeElements( int from, int to );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 */
-+ void addElements( int index, K a[] );
-+ /** Add (hopefully quickly) elements to this type-specific list.
-+	 *
-+	 * @param index the index at which to add elements.
-+	 * @param a the array containing the elements.
-+	 * @param offset the offset of the first element to add.
-+	 * @param length the number of elements to add.
-+	 */
-+ void addElements( int index, K a[], int offset, int length );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.ListIterator;
-+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
-+ *
-+ * <P>This interface merges the methods provided by a {@link ListIterator} and
-+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
-+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
-+ * and {@link java.util.ListIterator#set(Object) set()}.
-+ *
-+ * @see java.util.ListIterator
-+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
-+ */
-+public interface ObjectListIterator <K> extends ListIterator<K>, ObjectBidirectionalIterator <K> {
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Set;
-+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing. 
-+ *
-+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
-+ *
-+ * @see Set
-+ */
-+public interface ObjectSet <K> extends ObjectCollection <K>, Set<K> {
-+ /** Returns a type-specific iterator on the elements of this set.
-+	 *
-+	 * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
-+	 * which was already strengthened in the corresponding type-specific class,
-+	 * but was weakened by the fact that this interface extends {@link Set}.
-+	 *
-+	 * @return a type-specific iterator on the elements of this set.
-+	 */
-+ ObjectIterator <K> iterator();
-+ /** Removes an element from this set.
-+	 *
-+	 * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
-+	 * This unfortunate situation is caused by the clash
-+	 * with the similarly named index-based method in the {@link java.util.List} interface.
-+	 *
-+	 * @see java.util.Collection#remove(Object)
-+	 */
-+ public boolean remove( Object k );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.Collection;
-+import java.util.Set;
-+/** A class providing static methods and objects that do useful things with type-specific sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class ObjectSets {
-+ private ObjectSets() {}
-+ /** An immutable class representing the empty set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.
-+	 */
-+ public static class EmptySet <K> extends ObjectCollections.EmptyCollection <K> implements ObjectSet <K>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
-+  public Object clone() { return EMPTY_SET; }
-+  @SuppressWarnings("rawtypes")
-+  public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty set (immutable). It is serializable and cloneable.
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** Return an empty set (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
-+	 * @return an empty set (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> ObjectSet <K> emptySet() {
-+  return EMPTY_SET;
-+ }
-+ /** An immutable class representing a type-specific singleton set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific set.	 */
-+ public static class Singleton <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final K element;
-+  protected Singleton( final K element ) {
-+   this.element = element;
-+  }
-+  public boolean add( final K k ) { throw new UnsupportedOperationException(); }
-+  public boolean contains( final Object k ) { return ( (k) == null ? (element) == null : (k).equals(element) ); }
-+  public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
-+  public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
-+  public ObjectListIterator <K> iterator() { return ObjectIterators.singleton( element ); }
-+  public int size() { return 1; }
-+  public Object clone() { return this; }
-+ }
-+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned set.
-+	 * @return a type-specific immutable set containing just <code>element</code>.
-+	 */
-+ public static <K> ObjectSet <K> singleton( final K element ) {
-+  return new Singleton <K>( element );
-+ }
-+ /** A synchronized wrapper class for sets. */
-+ public static class SynchronizedSet <K> extends ObjectCollections.SynchronizedCollection <K> implements ObjectSet <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected SynchronizedSet( final ObjectSet <K> s, final Object sync ) {
-+   super( s, sync );
-+  }
-+  protected SynchronizedSet( final ObjectSet <K> s ) {
-+   super( s );
-+  }
-+  public boolean remove( final Object k ) { synchronized( sync ) { return collection.remove( (k) ); } }
-+  public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
-+  public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
-+ }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s ) { return new SynchronizedSet <K>( s ); }
-+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the set to be wrapped in a synchronized set.
-+	 * @param sync an object that will be used to synchronize the access to the set.
-+	 * @return a synchronized view of the specified set.
-+	 * @see java.util.Collections#synchronizedSet(Set)
-+	 */
-+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s, final Object sync ) { return new SynchronizedSet <K>( s, sync ); }
-+ /** An unmodifiable wrapper class for sets. */
-+ public static class UnmodifiableSet <K> extends ObjectCollections.UnmodifiableCollection <K> implements ObjectSet <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected UnmodifiableSet( final ObjectSet <K> s ) {
-+   super( s );
-+  }
-+  public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
-+  public boolean equals( final Object o ) { return collection.equals( o ); }
-+  public int hashCode() { return collection.hashCode(); }
-+ }
-+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
-+	 *
-+	 * @param s the set to be wrapped in an unmodifiable set.
-+	 * @return an unmodifiable view of the specified set.
-+	 * @see java.util.Collections#unmodifiableSet(Set)
-+	 */
-+ public static <K> ObjectSet <K> unmodifiable( final ObjectSet <K> s ) { return new UnmodifiableSet <K>( s ); }
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.SortedSet;
-+import java.util.Collection;
-+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
-+ *
-+ * <P>Additionally, this interface strengthens {@link #iterator()},
-+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)}, 
-+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
-+ *
-+ * @see SortedSet
-+ */
-+public interface ObjectSortedSet <K> extends ObjectSet <K>, SortedSet<K> {
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set, starting from a given element of the domain (optional operation).
-+	 *
-+	 * <P>This method returns a type-specific bidirectional iterator with given
-+	 * starting point. The starting point is any element comparable to the
-+	 * elements of this set (even if it does not actually belong to the
-+	 * set). The next element of the returned iterator is the least element of
-+	 * the set that is greater than the starting point (if there are no
-+	 * elements greater than the starting point, {@link
-+	 * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
-+	 * <code>false</code>). The previous element of the returned iterator is
-+	 * the greatest element of the set that is smaller than or equal to the
-+	 * starting point (if there are no elements smaller than or equal to the
-+	 * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
-+	 * hasPrevious()} will return <code>false</code>).
-+	 *  
-+	 * <P>Note that passing the last element of the set as starting point and
-+	 * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
-+	 * entire set in reverse order.
-+	 *
-+	 * @param fromElement an element to start from.
-+	 * @return a bidirectional iterator on the element in this set, starting at the given element.
-+	 * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
-+	 */
-+ ObjectBidirectionalIterator <K> iterator( K fromElement );
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
-+	 *
-+	 * <P>The iterator returned by the {@link #iterator()} method and by this
-+	 * method are identical; however, using this method you can save a type casting.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
-+	 */
-+ @Deprecated
-+ ObjectBidirectionalIterator <K> objectIterator();
-+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
-+	 * this set.
-+	 *
-+	 * <P>This method returns a parameterised bidirectional iterator. The iterator
-+	 * can be moreover safely cast to a type-specific iterator.
-+	 *
-+	 * Note that this specification strengthens the one given in the corresponding type-specific
-+	 * {@link Collection}.
-+	 *
-+	 * @return a bidirectional iterator on the element in this set. 
-+	 */
-+ ObjectBidirectionalIterator <K> iterator();
-+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
-+	 *
-+	 * @see SortedSet#subSet(Object,Object)
-+	 */
-+ ObjectSortedSet <K> subSet( K fromElement, K toElement) ;
-+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
-+	 *
-+	 * @see SortedSet#headSet(Object)
-+	 */
-+ ObjectSortedSet <K> headSet( K toElement );
-+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
-+	 *
-+	 * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
-+	 *
-+	 * @see SortedSet#tailSet(Object)
-+	 */
-+ ObjectSortedSet <K> tailSet( K fromElement );
-+}
-diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
-@@ -0,0 +0,0 @@
-+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
-+   This file is part of the GNU C Library.
-+
-+   The GNU C Library is free software; you can redistribute it and/or
-+   modify it under the terms of the GNU Lesser General Public
-+   License as published by the Free Software Foundation; either
-+   version 2.1 of the License, or (at your option) any later version.
-+
-+   The GNU C Library is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+   Lesser General Public License for more details.
-+
-+   You should have received a copy of the GNU Lesser General Public
-+   License along with the GNU C Library; if not, see
-+   <http://www.gnu.org/licenses/>.  */
-+/* This header is separate from features.h so that the compiler can
-+   include it implicitly at the start of every compilation.  It must
-+   not itself include <features.h> or any other header that includes
-+   <features.h> because the implicit include comes before any feature
-+   test macros that may be defined in a source file before it first
-+   explicitly includes a system header.  GCC knows the name of this
-+   header in order to preinclude it.  */
-+/* glibc's intent is to support the IEC 559 math functionality, real
-+   and complex.  If the GCC (4.9 and later) predefined macros
-+   specifying compiler intent are available, use them to determine
-+   whether the overall intent is to support these features; otherwise,
-+   presume an older compiler has intent to support these features and
-+   define these macros by default.  */
-+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
-+   Unicode 6.0.  */
-+/* We do not support C11 <threads.h>.  */
-+/* Generic definitions */
-+/* Assertions (useful to generate conditional code) */
-+/* Current type and class (and size, if applicable) */
-+/* Value methods */
-+/* Interfaces (keys) */
-+/* Interfaces (values) */
-+/* Abstract implementations (keys) */
-+/* Abstract implementations (values) */
-+/* Static containers (keys) */
-+/* Static containers (values) */
-+/* Implementations */
-+/* Synchronized wrappers */
-+/* Unmodifiable wrappers */
-+/* Other wrappers */
-+/* Methods (keys) */
-+/* Methods (values) */
-+/* Methods (keys/values) */
-+/* Methods that have special names depending on keys (but the special names depend on values) */
-+/* Equality */
-+/* Object/Reference-only definitions (keys) */
-+/* Object/Reference-only definitions (values) */
-+/*		 
-+ * Copyright (C) 2002-2016 Sebastiano Vigna
-+ *
-+ * 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 it.unimi.dsi.fastutil.objects;
-+import java.util.SortedSet;
-+import java.util.NoSuchElementException;
-+import java.util.Comparator;
-+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
-+ *
-+ * @see java.util.Collections
-+ */
-+public class ObjectSortedSets {
-+ private ObjectSortedSets() {}
-+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class EmptySet <K> extends ObjectSets.EmptySet <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected EmptySet() {}
-+  public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
-+  @Deprecated
-+  public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
-+  @SuppressWarnings("unchecked")
-+  public ObjectBidirectionalIterator <K> iterator( K from ) { return ObjectIterators.EMPTY_ITERATOR; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> subSet( K from, K to ) { return EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> headSet( K from ) { return EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> tailSet( K to ) { return EMPTY_SET; }
-+  public K first() { throw new NoSuchElementException(); }
-+  public K last() { throw new NoSuchElementException(); }
-+  public Comparator <? super K> comparator() { return null; }
-+  public Object clone() { return EMPTY_SET; }
-+        private Object readResolve() { return EMPTY_SET; }
-+ }
-+ /** An empty sorted set (immutable). It is serializable and cloneable.
-+	 *
-+	 */
-+ @SuppressWarnings("rawtypes")
-+ public static final EmptySet EMPTY_SET = new EmptySet();
-+ /** Return an empty sorted set (immutable). It is serializable and cloneable.
-+	 *
-+	 * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
-+	 * @return an empty sorted set (immutable).
-+	 */
-+ @SuppressWarnings("unchecked")
-+ public static <K> ObjectSet <K> emptySet() {
-+  return EMPTY_SET;
-+ }
-+ /** A class representing a singleton sorted set.
-+	 *
-+	 * <P>This class may be useful to implement your own in case you subclass
-+	 * a type-specific sorted set.
-+	 */
-+ public static class Singleton <K> extends ObjectSets.Singleton <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  final Comparator <? super K> comparator;
-+  private Singleton( final K element, final Comparator <? super K> comparator ) {
-+   super( element );
-+   this.comparator = comparator;
-+  }
-+  private Singleton( final K element ) {
-+   this( element, null );
-+  }
-+  @SuppressWarnings("unchecked")
-+  final int compare( final K k1, final K k2 ) {
-+   return comparator == null ? ( ((Comparable<K>)(k1)).compareTo(k2) ) : comparator.compare( k1, k2 );
-+  }
-+  @Deprecated
-+  public ObjectBidirectionalIterator <K> objectIterator() {
-+   return iterator();
-+  }
-+  public ObjectBidirectionalIterator <K> iterator( K from ) {
-+   ObjectBidirectionalIterator <K> i = iterator();
-+   if ( compare( element, from ) <= 0 ) i.next();
-+   return i;
-+  }
-+  public Comparator <? super K> comparator() { return comparator; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> subSet( final K from, final K to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> headSet( final K to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
-+  @SuppressWarnings("unchecked")
-+  public ObjectSortedSet <K> tailSet( final K from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
-+  public K first() { return element; }
-+  public K last() { return element; }
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static <K> ObjectSortedSet <K> singleton( final K element ) {
-+  return new Singleton <K>( element );
-+ }
-+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
-+	 *
-+	 * @param element the only element of the returned sorted set.
-+	 * @param comparator the comparator to use in the returned sorted set.
-+	 * @return a type-specific immutable sorted set containing just <code>element</code>.
-+	 */
-+ public static <K> ObjectSortedSet <K> singleton( final K element, final Comparator <? super K> comparator ) {
-+  return new Singleton <K>( element, comparator );
-+ }
-+ /** A synchronized wrapper class for sorted sets. */
-+ public static class SynchronizedSortedSet <K> extends ObjectSets.SynchronizedSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final ObjectSortedSet <K> sortedSet;
-+  protected SynchronizedSortedSet( final ObjectSortedSet <K> s, final Object sync ) {
-+   super( s, sync );
-+   sortedSet = s;
-+  }
-+  protected SynchronizedSortedSet( final ObjectSortedSet <K> s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public Comparator <? super K> comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
-+  public ObjectSortedSet <K> subSet( final K from, final K to ) { return new SynchronizedSortedSet <K>( sortedSet.subSet( from, to ), sync ); }
-+  public ObjectSortedSet <K> headSet( final K to ) { return new SynchronizedSortedSet <K>( sortedSet.headSet( to ), sync ); }
-+  public ObjectSortedSet <K> tailSet( final K from ) { return new SynchronizedSortedSet <K>( sortedSet.tailSet( from ), sync ); }
-+  public ObjectBidirectionalIterator <K> iterator() { return sortedSet.iterator(); }
-+  public ObjectBidirectionalIterator <K> iterator( final K from ) { return sortedSet.iterator( from ); }
-+  @Deprecated
-+  public ObjectBidirectionalIterator <K> objectIterator() { return sortedSet.iterator(); }
-+  public K first() { synchronized( sync ) { return sortedSet.first(); } }
-+  public K last() { synchronized( sync ) { return sortedSet.last(); } }
-+ }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s ) { return new SynchronizedSortedSet <K>( s ); }
-+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
-+	 *
-+	 * @param s the sorted set to be wrapped in a synchronized sorted set.
-+	 * @param sync an object that will be used to synchronize the access to the sorted set.
-+	 * @return a synchronized view of the specified sorted set.
-+	 * @see java.util.Collections#synchronizedSortedSet(SortedSet)
-+	 */
-+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s, final Object sync ) { return new SynchronizedSortedSet <K>( s, sync ); }
-+ /** An unmodifiable wrapper class for sorted sets. */
-+ public static class UnmodifiableSortedSet <K> extends ObjectSets.UnmodifiableSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
-+  private static final long serialVersionUID = -7046029254386353129L;
-+  protected final ObjectSortedSet <K> sortedSet;
-+  protected UnmodifiableSortedSet( final ObjectSortedSet <K> s ) {
-+   super( s );
-+   sortedSet = s;
-+  }
-+  public Comparator <? super K> comparator() { return sortedSet.comparator(); }
-+  public ObjectSortedSet <K> subSet( final K from, final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.subSet( from, to ) ); }
-+  public ObjectSortedSet <K> headSet( final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.headSet( to ) ); }
-+  public ObjectSortedSet <K> tailSet( final K from ) { return new UnmodifiableSortedSet <K>( sortedSet.tailSet( from ) ); }
-+  public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.unmodifiable( sortedSet.iterator() ); }
-+  public ObjectBidirectionalIterator <K> iterator( final K from ) { return ObjectIterators.unmodifiable( sortedSet.iterator( from ) ); }
-+  @Deprecated
-+  public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
-+  public K first() { return sortedSet.first(); }
-+  public K last() { return sortedSet.last(); }
-+ }
-+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
-+	 *
-+	 * @param s the sorted set to be wrapped in an unmodifiable sorted set.
-+	 * @return an unmodifiable view of the specified sorted set.
-+	 * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
-+	 */
-+ public static <K> ObjectSortedSet <K> unmodifiable( final ObjectSortedSet <K> s ) { return new UnmodifiableSortedSet <K>( s ); }
-+}
---
\ No newline at end of file
diff --git a/Spigot-API-Patches/Timings-v2.patch b/Spigot-API-Patches/Timings-v2.patch
index 878edf15b2..784071a5f1 100644
--- a/Spigot-API-Patches/Timings-v2.patch
+++ b/Spigot-API-Patches/Timings-v2.patch
@@ -4,29 +4,6 @@ Date: Mon, 29 Feb 2016 18:48:17 -0600
 Subject: [PATCH] Timings v2
 
 
-diff --git a/pom.xml b/pom.xml
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/pom.xml
-+++ b/pom.xml
-@@ -0,0 +0,0 @@
--
- <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-     <modelVersion>4.0.0</modelVersion>
-@@ -0,0 +0,0 @@
- 
-     <dependencies>
-         <dependency>
-+            <groupId>net.sf.trove4j</groupId>
-+            <artifactId>trove4j</artifactId>
-+            <version>3.0.3</version>
-+            <!-- Trove Provided by CraftBukkit -->
-+            <scope>provided</scope>
-+        </dependency>
-+        <dependency>
-             <groupId>commons-lang</groupId>
-             <artifactId>commons-lang</artifactId>
-             <version>2.6</version>
 diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
diff --git a/Spigot-API-Patches/add-Trove-and-FastUtil-to-Bukkit.patch b/Spigot-API-Patches/add-Trove-and-FastUtil-to-Bukkit.patch
new file mode 100644
index 0000000000..a1f693c07f
--- /dev/null
+++ b/Spigot-API-Patches/add-Trove-and-FastUtil-to-Bukkit.patch
@@ -0,0 +1,31 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <aikar@aikar.co>
+Date: Fri, 1 Apr 2016 00:02:47 -0400
+Subject: [PATCH] add Trove and FastUtil to Bukkit
+
+
+diff --git a/pom.xml b/pom.xml
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -0,0 +0,0 @@
+ 
+     <dependencies>
+         <dependency>
++            <groupId>net.sf.trove4j</groupId>
++            <artifactId>trove4j</artifactId>
++            <version>3.0.3</version>
++            <!-- Trove Provided by CraftBukkit -->
++            <scope>provided</scope>
++        </dependency>
++        <dependency>
++            <groupId>co.aikar</groupId>
++            <artifactId>fastutil-lite</artifactId>
++            <version>1.0</version>
++            <scope>provided</scope>
++        </dependency>
++        <dependency>
+             <groupId>commons-lang</groupId>
+             <artifactId>commons-lang</artifactId>
+             <version>2.6</version>
+--
\ No newline at end of file
diff --git a/Spigot-Server-Patches/EAR-Fix-bug-with-teleporting-entities.patch b/Spigot-Server-Patches/EAR-Fix-bug-with-teleporting-entities.patch
index 459469a17e..5e1ba2f56f 100644
--- a/Spigot-Server-Patches/EAR-Fix-bug-with-teleporting-entities.patch
+++ b/Spigot-Server-Patches/EAR-Fix-bug-with-teleporting-entities.patch
@@ -31,6 +31,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      public boolean ah;
      public boolean impulse;
      public int portalCooldown;
+diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/net/minecraft/server/World.java
++++ b/src/main/java/net/minecraft/server/World.java
+@@ -0,0 +0,0 @@ public abstract class World implements IBlockAccess {
+         byte b0 = 32;
+ 
+         // Spigot start
+-        if (!org.spigotmc.ActivationRange.checkIfActive(entity)) {
++        if (flag && !org.spigotmc.ActivationRange.checkIfActive(entity)) {
+             entity.ticksLived++;
+             entity.inactiveTick();
+         } else {
 diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
 --- a/src/main/java/org/spigotmc/ActivationRange.java
diff --git a/Spigot-Server-Patches/Timings-v2.patch b/Spigot-Server-Patches/Timings-v2.patch
index 681ed48ce5..356bbd1dc6 100644
--- a/Spigot-Server-Patches/Timings-v2.patch
+++ b/Spigot-Server-Patches/Timings-v2.patch
@@ -4,6 +4,23 @@ Date: Thu, 3 Mar 2016 04:00:11 -0600
 Subject: [PATCH] Timings v2
 
 
+diff --git a/pom.xml b/pom.xml
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/pom.xml
++++ b/pom.xml
+@@ -0,0 +0,0 @@
+             <scope>compile</scope>
+         </dependency>
+         <dependency>
++            <groupId>co.aikar</groupId>
++            <artifactId>fastutil-lite</artifactId>
++            <version>1.0</version>
++            <scope>provided</scope>
++        </dependency>
++        <dependency>
+             <groupId>net.sf.trove4j</groupId>
+             <artifactId>trove4j</artifactId>
+             <version>3.0.3</version>
 diff --git a/src/main/java/co/aikar/timings/SpigotTimings.java b/src/main/java/co/aikar/timings/SpigotTimings.java
 new file mode 100644
 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
diff --git a/pom.xml b/pom.xml
index 066f8d8893..ee0f11f169 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,10 @@
             <id>md_5-releases</id>
             <url>http://repo.md-5.net/content/repositories/releases/</url>
         </repository>
+        <repository>
+            <id>aikar</id>
+            <url>https://ci.emc.gs/nexus/content/repositories/aikar/</url>
+        </repository>
     </repositories>
 
     <distributionManagement>
@@ -48,4 +52,4 @@
             <url>https://repo.destroystokyo.com/content/repositories/snapshots/</url>
         </snapshotRepository>
     </distributionManagement>
-</project>
\ No newline at end of file
+</project>