diff --git a/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch b/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch
new file mode 100644
index 000000000..76155c394
--- /dev/null
+++ b/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch
@@ -0,0 +1,45209 @@
+From 8856eed99403409f9904fb8315ff4f2e95065239 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 based collections
+
+
+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 0000000..4778cfa
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
+@@ -0,0 +1,29 @@
++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 0000000..7138801
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
+@@ -0,0 +1,41 @@
++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 0000000..7e819f3
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
+@@ -0,0 +1,35 @@
++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 0000000..faf3e7c
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
+@@ -0,0 +1,41 @@
++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 0000000..e57cc0a
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
+@@ -0,0 +1,437 @@
++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 0000000..526d78e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
+@@ -0,0 +1,55 @@
++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 0000000..8f891db
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
+@@ -0,0 +1,32 @@
++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 0000000..03bb61b
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Function.java
+@@ -0,0 +1,101 @@
++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 0000000..2b52e19
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Hash.java
+@@ -0,0 +1,173 @@
++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 0000000..1d42f80
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
+@@ -0,0 +1,240 @@
++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 0000000..97ce3c5
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
+@@ -0,0 +1,61 @@
++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 0000000..f85a2a7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
+@@ -0,0 +1,110 @@
++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 0000000..74d1a16
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
+@@ -0,0 +1,162 @@
++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 0000000..a96837c
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
+@@ -0,0 +1,118 @@
++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 0000000..6934251
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Maps.java
+@@ -0,0 +1,36 @@
++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 0000000..fe80c6b
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
+@@ -0,0 +1,102 @@
++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 0000000..eba43d7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
+@@ -0,0 +1,109 @@
++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 0000000..05ff4cc
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Size64.java
+@@ -0,0 +1,50 @@
++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 0000000..2a601a9
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Stack.java
+@@ -0,0 +1,73 @@
++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 0000000..5d4e2cb
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
+@@ -0,0 +1,31 @@
++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 0000000..fba1030
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
+@@ -0,0 +1,150 @@
++/* 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 0000000..9579648
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
+@@ -0,0 +1,271 @@
++/* 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 0000000..4b4191b
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
+@@ -0,0 +1,193 @@
++/* 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 0000000..ef90e23
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
+@@ -0,0 +1,95 @@
++/* 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 0000000..b704d10
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
+@@ -0,0 +1,271 @@
++/* 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 0000000..2eb1121
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
+@@ -0,0 +1,87 @@
++/* 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 0000000..4fc1be5
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
+@@ -0,0 +1,100 @@
++/* 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 0000000..4a32979
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
+@@ -0,0 +1,577 @@
++/* 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 0000000..981123f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
+@@ -0,0 +1,92 @@
++/* 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 0000000..b3bc90f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
+@@ -0,0 +1,95 @@
++/* 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 0000000..97f3bff
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
+@@ -0,0 +1,115 @@
++/* 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 0000000..fb55816
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
+@@ -0,0 +1,110 @@
++/* 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 0000000..ba0a282
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
+@@ -0,0 +1,112 @@
++/* 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 0000000..fec4cdc
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
+@@ -0,0 +1,1655 @@
++/* 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 0000000..2b637a3
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
+@@ -0,0 +1,346 @@
++/* 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 0000000..489609b
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
+@@ -0,0 +1,137 @@
++/* 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 0000000..d288c35
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
+@@ -0,0 +1,224 @@
++/* 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 0000000..5564407
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
+@@ -0,0 +1,1444 @@
++/* 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 0000000..b0cba54
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
+@@ -0,0 +1,151 @@
++/* 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 0000000..2c0741e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
+@@ -0,0 +1,312 @@
++/* 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 0000000..49bebcb
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
+@@ -0,0 +1,922 @@
++/* 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 0000000..b392723
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
+@@ -0,0 +1,901 @@
++/* 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 0000000..dae82fa
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
+@@ -0,0 +1,1599 @@
++/* 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 0000000..04fbc68
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
+@@ -0,0 +1,181 @@
++/* 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 0000000..49e4cc7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
+@@ -0,0 +1,326 @@
++/* 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 0000000..d6835e9
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
+@@ -0,0 +1,226 @@
++/* 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 0000000..34bf5c0
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
+@@ -0,0 +1,295 @@
++/* 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 0000000..ec18eae
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
+@@ -0,0 +1,501 @@
++/* 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 0000000..dcf704d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
+@@ -0,0 +1,229 @@
++/* 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 0000000..af8014d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
+@@ -0,0 +1,218 @@
++/* 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 0000000..e9d8586
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
+@@ -0,0 +1,2462 @@
++/* 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 0000000..04df663
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
+@@ -0,0 +1,97 @@
++/* 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 0000000..56a2d21
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
+@@ -0,0 +1,169 @@
++/* 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 0000000..fbf2c95
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
+@@ -0,0 +1,237 @@
++/* 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 0000000..cb84b48
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
+@@ -0,0 +1,90 @@
++/* 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 0000000..04e7ce7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
+@@ -0,0 +1,113 @@
++/* 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 0000000..7b7753e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
+@@ -0,0 +1,96 @@
++/* 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 0000000..94da704
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
+@@ -0,0 +1,227 @@
++/* 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 0000000..b9f9796
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
+@@ -0,0 +1,251 @@
++/* 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 0000000..f294993
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
+@@ -0,0 +1,243 @@
++/* 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 0000000..ab987b7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
+@@ -0,0 +1,155 @@
++/* 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 0000000..53f3e35
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
+@@ -0,0 +1,191 @@
++/* 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 0000000..a950eff
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
+@@ -0,0 +1,85 @@
++/* 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 0000000..a0c323f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
+@@ -0,0 +1,88 @@
++/* 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 0000000..c6e9fc9
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
+@@ -0,0 +1,96 @@
++/* 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 0000000..324c12c
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
+@@ -0,0 +1,637 @@
++/* 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 0000000..ac197b8
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
+@@ -0,0 +1,1071 @@
++/* 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 0000000..8d7e9ad
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
+@@ -0,0 +1,1044 @@
++/* 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 0000000..b8aeebd
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
+@@ -0,0 +1,210 @@
++/* 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 0000000..758146f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
+@@ -0,0 +1,85 @@
++/* 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 0000000..ea909a8
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
+@@ -0,0 +1,334 @@
++/* 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 0000000..7517420
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
+@@ -0,0 +1,108 @@
++/* 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 0000000..4d54aa0
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
+@@ -0,0 +1,116 @@
++/* 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 0000000..9e517f5
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
+@@ -0,0 +1,268 @@
++/* 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 0000000..9d8a21f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
+@@ -0,0 +1,97 @@
++/* 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 0000000..69c8c44
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
+@@ -0,0 +1,186 @@
++/* 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 0000000..ba95523
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
+@@ -0,0 +1,179 @@
++/* 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 0000000..56623dc
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
+@@ -0,0 +1,280 @@
++/* 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 0000000..71ac087
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
+@@ -0,0 +1,91 @@
++/* 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 0000000..7fe95f1
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
+@@ -0,0 +1,12 @@
++<!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 0000000..3ef4991
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
+@@ -0,0 +1,150 @@
++/* 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 0000000..1b2c09f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
+@@ -0,0 +1,271 @@
++/* 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 0000000..3b5ca83
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
+@@ -0,0 +1,193 @@
++/* 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 0000000..63ee559
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
+@@ -0,0 +1,95 @@
++/* 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 0000000..fdd3120
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
+@@ -0,0 +1,271 @@
++/* 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 0000000..f437517
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
+@@ -0,0 +1,87 @@
++/* 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 0000000..610c855
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
+@@ -0,0 +1,100 @@
++/* 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 0000000..d4f51d2
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
+@@ -0,0 +1,577 @@
++/* 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 0000000..963a9cd
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
+@@ -0,0 +1,92 @@
++/* 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 0000000..f7606fb
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
+@@ -0,0 +1,95 @@
++/* 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 0000000..91c6eef
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
+@@ -0,0 +1,115 @@
++/* 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 0000000..84bd619
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
+@@ -0,0 +1,110 @@
++/* 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 0000000..23ece85
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
+@@ -0,0 +1,346 @@
++/* 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 0000000..be0234e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
+@@ -0,0 +1,137 @@
++/* 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 0000000..5afe8fb
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
+@@ -0,0 +1,224 @@
++/* 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 0000000..d221ba0
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
+@@ -0,0 +1,1444 @@
++/* 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 0000000..afbb18d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
+@@ -0,0 +1,151 @@
++/* 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 0000000..9047158
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
+@@ -0,0 +1,312 @@
++/* 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 0000000..547fcbf
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
+@@ -0,0 +1,922 @@
++/* 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 0000000..9666263
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
+@@ -0,0 +1,901 @@
++/* 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 0000000..365ebc7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
+@@ -0,0 +1,181 @@
++/* 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 0000000..1a91791
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
+@@ -0,0 +1,326 @@
++/* 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 0000000..6242492
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
+@@ -0,0 +1,226 @@
++/* 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 0000000..11d1194
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
+@@ -0,0 +1,501 @@
++/* 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 0000000..8b3f90d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
+@@ -0,0 +1,229 @@
++/* 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 0000000..d9e82a2
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
+@@ -0,0 +1,218 @@
++/* 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 0000000..0f453ac
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
+@@ -0,0 +1,2463 @@
++/* 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 0000000..ae2906f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
+@@ -0,0 +1,97 @@
++/* 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 0000000..0708d1f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
+@@ -0,0 +1,169 @@
++/* 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 0000000..1574de8
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
+@@ -0,0 +1,237 @@
++/* 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 0000000..31e394a
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
+@@ -0,0 +1,90 @@
++/* 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 0000000..7098bbc
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
+@@ -0,0 +1,113 @@
++/* 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 0000000..5b394ab
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
+@@ -0,0 +1,96 @@
++/* 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 0000000..b63b1a2
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
+@@ -0,0 +1,155 @@
++/* 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 0000000..b9bdf8b
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
+@@ -0,0 +1,88 @@
++/* 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 0000000..9838448
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
+@@ -0,0 +1,96 @@
++/* 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 0000000..1d71ab0
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
+@@ -0,0 +1,658 @@
++/* 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 0000000..bc91a8f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
+@@ -0,0 +1,210 @@
++/* 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 0000000..e977a00
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
+@@ -0,0 +1,85 @@
++/* 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 0000000..cff8a3c
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
+@@ -0,0 +1,334 @@
++/* 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 0000000..b6a8b42
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
+@@ -0,0 +1,661 @@
++/* 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 0000000..bcafa3e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
+@@ -0,0 +1,627 @@
++/* 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 0000000..de4db2d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
+@@ -0,0 +1,108 @@
++/* 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 0000000..88dfc23
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
+@@ -0,0 +1,116 @@
++/* 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 0000000..c7dad79
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
+@@ -0,0 +1,97 @@
++/* 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 0000000..de7e3da
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
+@@ -0,0 +1,186 @@
++/* 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 0000000..7490285
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
+@@ -0,0 +1,179 @@
++/* 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 0000000..73e7361
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
+@@ -0,0 +1,280 @@
++/* 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 0000000..3627a64
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
+@@ -0,0 +1,91 @@
++/* 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 0000000..772ffd4
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
+@@ -0,0 +1,12 @@
++<!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 0000000..4828c8c
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
+@@ -0,0 +1,90 @@
++/* 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 0000000..bd437e7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
+@@ -0,0 +1,175 @@
++/* 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 0000000..654db5f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
+@@ -0,0 +1,93 @@
++/* 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 0000000..41303ac
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
+@@ -0,0 +1,472 @@
++/* 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 0000000..b7de919
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
+@@ -0,0 +1,87 @@
++/* 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 0000000..7bb6799
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
+@@ -0,0 +1,102 @@
++/* 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 0000000..6712d6d
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
+@@ -0,0 +1,79 @@
++/* 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 0000000..bce9171
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
+@@ -0,0 +1,510 @@
++/* 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 0000000..8b8dd8e
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
+@@ -0,0 +1,220 @@
++/* 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 0000000..e56a0f8
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
+@@ -0,0 +1,1594 @@
++/* 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 0000000..2dc5150
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
+@@ -0,0 +1,88 @@
++/* 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 0000000..e169594
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
+@@ -0,0 +1,109 @@
++/* 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 0000000..e6c2991
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
+@@ -0,0 +1,212 @@
++/* 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 0000000..5835740
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
+@@ -0,0 +1,87 @@
++/* 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 0000000..b3af95f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
+@@ -0,0 +1,88 @@
++/* 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 0000000..f4c7afd
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
+@@ -0,0 +1,558 @@
++/* 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 0000000..7b376b7
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
+@@ -0,0 +1,169 @@
++/* 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 0000000..f7f0b36
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
+@@ -0,0 +1,82 @@
++/* 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 0000000..02fa79f
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
+@@ -0,0 +1,96 @@
++/* 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 0000000..63e5049
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
+@@ -0,0 +1,177 @@
++/* 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 0000000..d2777fb
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
+@@ -0,0 +1,151 @@
++/* 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 0000000..b6142a0
+--- /dev/null
++++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
+@@ -0,0 +1,237 @@
++/* 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 ); }
++}
+-- 
+2.8.0
+
diff --git a/Spigot-API-Patches/0002-Timings-v2.patch b/Spigot-API-Patches/0003-Timings-v2.patch
similarity index 100%
rename from Spigot-API-Patches/0002-Timings-v2.patch
rename to Spigot-API-Patches/0003-Timings-v2.patch
diff --git a/Spigot-API-Patches/0003-Player-affects-spawning-API.patch b/Spigot-API-Patches/0004-Player-affects-spawning-API.patch
similarity index 90%
rename from Spigot-API-Patches/0003-Player-affects-spawning-API.patch
rename to Spigot-API-Patches/0004-Player-affects-spawning-API.patch
index cb73d630e..babadf82c 100644
--- a/Spigot-API-Patches/0003-Player-affects-spawning-API.patch
+++ b/Spigot-API-Patches/0004-Player-affects-spawning-API.patch
@@ -1,11 +1,11 @@
-From 5ae17d42515dab32a03341740fd3b99aeb4c4420 Mon Sep 17 00:00:00 2001
+From e5bf28b61af878aee9b97ab52d6ed6930487362f Mon Sep 17 00:00:00 2001
 From: Jedediah Smith <jedediah@silencegreys.com>
 Date: Mon, 29 Feb 2016 17:22:34 -0600
 Subject: [PATCH] Player affects spawning API
 
 
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 3242c69..0979f94 100644
+index 19f7ae7..145bb15 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -1270,6 +1270,20 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
@@ -30,5 +30,5 @@ index 3242c69..0979f94 100644
      public class Spigot extends Entity.Spigot
      {
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0004-Add-getTPS-method.patch b/Spigot-API-Patches/0005-Add-getTPS-method.patch
similarity index 94%
rename from Spigot-API-Patches/0004-Add-getTPS-method.patch
rename to Spigot-API-Patches/0005-Add-getTPS-method.patch
index 901837b19..cd9252ec2 100644
--- a/Spigot-API-Patches/0004-Add-getTPS-method.patch
+++ b/Spigot-API-Patches/0005-Add-getTPS-method.patch
@@ -1,4 +1,4 @@
-From c84a859dcf623824d3fa4f45d0fdb00c96f791a3 Mon Sep 17 00:00:00 2001
+From f41ba48d012b47e2ea11fae6e58e595e93ba47e1 Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 29 Feb 2016 17:24:57 -0600
 Subject: [PATCH] Add getTPS method
@@ -42,5 +42,5 @@ index f82cbaf..6e23b0c 100644
       * @return the unsafe values instance
       */
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0005-Add-async-chunk-load-API.patch b/Spigot-API-Patches/0006-Add-async-chunk-load-API.patch
similarity index 97%
rename from Spigot-API-Patches/0005-Add-async-chunk-load-API.patch
rename to Spigot-API-Patches/0006-Add-async-chunk-load-API.patch
index 6175ac1a9..28f2d800d 100644
--- a/Spigot-API-Patches/0005-Add-async-chunk-load-API.patch
+++ b/Spigot-API-Patches/0006-Add-async-chunk-load-API.patch
@@ -1,4 +1,4 @@
-From 185a0dc471a2a1f5c74365f576ef3fecc04077cf Mon Sep 17 00:00:00 2001
+From 410427fe9f7aa75592d7ba4aec7cfc78ae868da7 Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 29 Feb 2016 17:43:33 -0600
 Subject: [PATCH] Add async chunk load API
@@ -88,5 +88,5 @@ index d088c3c..d16facb 100644
       *
       * @param chunk The chunk to check
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0006-Entity-Origin-API.patch b/Spigot-API-Patches/0007-Entity-Origin-API.patch
similarity index 96%
rename from Spigot-API-Patches/0006-Entity-Origin-API.patch
rename to Spigot-API-Patches/0007-Entity-Origin-API.patch
index 706216082..6355ad239 100644
--- a/Spigot-API-Patches/0006-Entity-Origin-API.patch
+++ b/Spigot-API-Patches/0007-Entity-Origin-API.patch
@@ -1,4 +1,4 @@
-From fc936348f326dc7f042c1791eb98627a7fa97008 Mon Sep 17 00:00:00 2001
+From 80f0b1f242c4e32979a05cc74f0e482c2fdbc0fa Mon Sep 17 00:00:00 2001
 From: Byteflux <byte@byteflux.net>
 Date: Mon, 29 Feb 2016 17:50:31 -0600
 Subject: [PATCH] Entity Origin API
@@ -61,5 +61,5 @@ index 3ce322d..69df487 100644
 +    public org.bukkit.Location getSourceLoc();
  }
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0007-Check-Paper-versions.patch b/Spigot-API-Patches/0008-Check-Paper-versions.patch
similarity index 98%
rename from Spigot-API-Patches/0007-Check-Paper-versions.patch
rename to Spigot-API-Patches/0008-Check-Paper-versions.patch
index 91619a849..121ebfbd9 100644
--- a/Spigot-API-Patches/0007-Check-Paper-versions.patch
+++ b/Spigot-API-Patches/0008-Check-Paper-versions.patch
@@ -1,4 +1,4 @@
-From 8945fdcb9e256a858154ee2bd510b0be242c9258 Mon Sep 17 00:00:00 2001
+From 1c6c69b96da276f32ff330c25091299c3efd1fbd Mon Sep 17 00:00:00 2001
 From: Zach Brown <zach.brown@destroystokyo.com>
 Date: Mon, 29 Feb 2016 17:58:01 -0600
 Subject: [PATCH] Check Paper versions
@@ -139,5 +139,5 @@ index b55abdb..6d32e1d 100644
 +    // Paper end
  }
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch b/Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch
similarity index 95%
rename from Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch
rename to Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch
index 02614623d..96dbbb26d 100644
--- a/Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch
+++ b/Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch
@@ -1,4 +1,4 @@
-From bb0becc6c80fa0996078cc9e7d5bb3e0dea72611 Mon Sep 17 00:00:00 2001
+From 5bbfd17e10b92832b0459da91bb1044c3eb38f17 Mon Sep 17 00:00:00 2001
 From: Isaac Moore <rmsy@me.com>
 Date: Mon, 29 Feb 2016 18:02:25 -0600
 Subject: [PATCH] Add PlayerLocaleChangeEvent
@@ -58,5 +58,5 @@ index 0000000..17afc8c
 +    }
 +}
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0009-Add-player-view-distance-API.patch b/Spigot-API-Patches/0010-Add-player-view-distance-API.patch
similarity index 89%
rename from Spigot-API-Patches/0009-Add-player-view-distance-API.patch
rename to Spigot-API-Patches/0010-Add-player-view-distance-API.patch
index 3027cd6e5..8fa2ba809 100644
--- a/Spigot-API-Patches/0009-Add-player-view-distance-API.patch
+++ b/Spigot-API-Patches/0010-Add-player-view-distance-API.patch
@@ -1,11 +1,11 @@
-From a4a5ff9f015a914a3967d0392769a74190945cba Mon Sep 17 00:00:00 2001
+From ddf27421558eedfa849d43c38652e43e6b785145 Mon Sep 17 00:00:00 2001
 From: Byteflux <byte@byteflux.net>
 Date: Mon, 29 Feb 2016 18:05:37 -0600
 Subject: [PATCH] Add player view distance API
 
 
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 0979f94..1a11c2b 100644
+index 145bb15..66527ce 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -1284,6 +1284,20 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
@@ -30,5 +30,5 @@ index 0979f94..1a11c2b 100644
      public class Spigot extends Entity.Spigot
      {
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch b/Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch
similarity index 96%
rename from Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch
rename to Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch
index 4de1ba4dd..0f8bb9975 100644
--- a/Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch
+++ b/Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch
@@ -1,4 +1,4 @@
-From dcd1942fd0c3527281f9411bd7c4103ebdf00f1e Mon Sep 17 00:00:00 2001
+From 93d98d9a2a4d8cbef43ca5b9e7fbad4d6cf925a5 Mon Sep 17 00:00:00 2001
 From: Byteflux <byte@byteflux.net>
 Date: Mon, 29 Feb 2016 18:09:40 -0600
 Subject: [PATCH] Add BeaconEffectEvent
@@ -92,5 +92,5 @@ index 0000000..6579ae9
 +    }
 +}
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch b/Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch
similarity index 95%
rename from Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch
rename to Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch
index 5fe29f067..625d6bd6d 100644
--- a/Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch
+++ b/Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch
@@ -1,4 +1,4 @@
-From 3eba221a754f0bdf4bc31cc105ed33757d4ab7f0 Mon Sep 17 00:00:00 2001
+From 3dabbf24d9e169631ff0f11df707e0623c4d2cc4 Mon Sep 17 00:00:00 2001
 From: Steve Anton <anxuiz.nx@gmail.com>
 Date: Mon, 29 Feb 2016 18:13:58 -0600
 Subject: [PATCH] Add PlayerInitialSpawnEvent
@@ -55,5 +55,5 @@ index 0000000..d1d6f33
 +    }
 +}
 -- 
-2.7.1.windows.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch b/Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch
similarity index 99%
rename from Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch
rename to Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch
index b030d3296..7ce83ab32 100644
--- a/Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch
+++ b/Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch
@@ -1,4 +1,4 @@
-From 78cc4ff51183b89e12aa39a47d39bf06497613ea Mon Sep 17 00:00:00 2001
+From 95affa5d23889fc61fbc4a2c37879369754609c3 Mon Sep 17 00:00:00 2001
 From: DemonWav <demonwav@gmail.com>
 Date: Mon, 29 Feb 2016 19:37:41 -0600
 Subject: [PATCH] Add Location support to tab completers (vanilla feature
@@ -165,5 +165,5 @@ index 6d61e3a..85b10e5 100644
 +    // Paper end
  }
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch b/Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch
similarity index 95%
rename from Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch
rename to Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch
index 16277b76f..9efcf8a04 100644
--- a/Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch
+++ b/Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch
@@ -1,4 +1,4 @@
-From ae556b9d833294cf0e1f865b6851447a11cdcda5 Mon Sep 17 00:00:00 2001
+From 72bedfe51658b0464677c52347151e5525b85307 Mon Sep 17 00:00:00 2001
 From: Nik Gil <nikmanG@users.noreply.github.com>
 Date: Mon, 29 Feb 2016 19:42:10 -0600
 Subject: [PATCH] Made EntityDismountEvent Cancellable
@@ -43,5 +43,5 @@ index 24d4942..ce989bb 100644
 +    // Paper end
  }
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch b/Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch
similarity index 93%
rename from Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch
rename to Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch
index 78feefc3f..41650100a 100644
--- a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch
+++ b/Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch
@@ -1,4 +1,4 @@
-From 9003dd80621ac325f76aab4af72047c9da57f691 Mon Sep 17 00:00:00 2001
+From 9b9ccba2ed63a98b146b388fd175e9d350e05dfd Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 29 Feb 2016 19:45:21 -0600
 Subject: [PATCH] Automatically disable plugins that fail to load
@@ -20,5 +20,5 @@ index 4983ea8..93a43dd 100644
  
              // Perhaps abort here, rather than continue going, but as it stands,
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch b/Spigot-API-Patches/0016-Expose-server-CommandMap.patch
similarity index 95%
rename from Spigot-API-Patches/0015-Expose-server-CommandMap.patch
rename to Spigot-API-Patches/0016-Expose-server-CommandMap.patch
index 1e2c2b8a8..1c8df1648 100644
--- a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch
+++ b/Spigot-API-Patches/0016-Expose-server-CommandMap.patch
@@ -1,4 +1,4 @@
-From 7c9892de7be9a27ba1014d2ee6202c70230b114d Mon Sep 17 00:00:00 2001
+From e56e4b8d652e65f05ed1102a811ec81508f7af4a Mon Sep 17 00:00:00 2001
 From: kashike <kashike@vq.lc>
 Date: Mon, 29 Feb 2016 19:48:59 -0600
 Subject: [PATCH] Expose server CommandMap
@@ -39,7 +39,7 @@ index 8d602a3..b6a0b40 100644
      {
          return server.spigot();
 diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index 86fe389..9ee3815 100644
+index 6e23b0c..a1ce356 100644
 --- a/src/main/java/org/bukkit/Server.java
 +++ b/src/main/java/org/bukkit/Server.java
 @@ -17,10 +17,7 @@ import org.bukkit.boss.BarColor;
@@ -70,5 +70,5 @@ index 86fe389..9ee3815 100644
       * @see UnsafeValues
       * @return the unsafe values instance
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch
similarity index 95%
rename from Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch
rename to Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch
index 254b7bd7a..24a1137e8 100644
--- a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch
+++ b/Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch
@@ -1,4 +1,4 @@
-From 47ecb6bf0557814cd48f9b732e1bd5bee223f923 Mon Sep 17 00:00:00 2001
+From ab8308a04ebe3b5e2ff0a93c1527b335a3d5f3a7 Mon Sep 17 00:00:00 2001
 From: Zach Brown <zach.brown@destroystokyo.com>
 Date: Mon, 29 Feb 2016 19:54:32 -0600
 Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses
@@ -36,7 +36,7 @@ index b6a0b40..f93ca2e 100644
       * Gets the name of the update folder. The update folder is used to safely
       * update plugins at the right moment on a plugin load.
 diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index 9ee3815..77d4f34 100644
+index a1ce356..91bde81 100644
 --- a/src/main/java/org/bukkit/Server.java
 +++ b/src/main/java/org/bukkit/Server.java
 @@ -238,6 +238,22 @@ public interface Server extends PluginMessageRecipient {
@@ -63,7 +63,7 @@ index 9ee3815..77d4f34 100644
       * Gets the name of the update folder. The update folder is used to safely
       * update plugins at the right moment on a plugin load.
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 855bde5..024b8dd 100644
+index 66527ce..edf35f5 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -331,6 +331,22 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
@@ -90,5 +90,5 @@ index 855bde5..024b8dd 100644
       * Forces an update of the player's entire inventory.
       *
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch b/Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch
similarity index 99%
rename from Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch
rename to Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch
index 3d592a99c..464543e54 100644
--- a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch
+++ b/Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch
@@ -1,4 +1,4 @@
-From 084b100716809ddb5c563ed03318c2cb010f7382 Mon Sep 17 00:00:00 2001
+From a0fabc2ea5c62e58d9c7caef415eabe3de6c9fb8 Mon Sep 17 00:00:00 2001
 From: Techcable <Techcable@outlook.com>
 Date: Mon, 29 Feb 2016 20:02:40 -0600
 Subject: [PATCH] Player Tab List and Title APIs
@@ -369,7 +369,7 @@ index 0000000..e1ecd44
 +    }
 +}
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 024b8dd..50a6a41 100644
+index edf35f5..5326ea6 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -2,6 +2,7 @@ package org.bukkit.entity;
@@ -507,5 +507,5 @@ index 024b8dd..50a6a41 100644
  
  
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch b/Spigot-API-Patches/0019-Add-exception-reporting-event.patch
similarity index 99%
rename from Spigot-API-Patches/0018-Add-exception-reporting-event.patch
rename to Spigot-API-Patches/0019-Add-exception-reporting-event.patch
index ae12c5b91..ff7f9336e 100644
--- a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch
+++ b/Spigot-API-Patches/0019-Add-exception-reporting-event.patch
@@ -1,4 +1,4 @@
-From d6d60f8002718e1a350932f6d62cd10babcb4c53 Mon Sep 17 00:00:00 2001
+From dec653a0fcd117f48e13a63d763fd7387d1d58a0 Mon Sep 17 00:00:00 2001
 From: Zach Brown <zach.brown@destroystokyo.com>
 Date: Mon, 29 Feb 2016 20:24:35 -0600
 Subject: [PATCH] Add exception reporting event
@@ -587,5 +587,5 @@ index 1325b03..49f5872 100644
          }
      }
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch
similarity index 96%
rename from Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch
rename to Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch
index 2d47507f7..468fa45d5 100644
--- a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch
+++ b/Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch
@@ -1,4 +1,4 @@
-From c872380e8a9e221324e69639a39bffb18fc8f883 Mon Sep 17 00:00:00 2001
+From 40cea5b463eada81ab6b30330ed739615a97c9bd Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 29 Feb 2016 20:26:39 -0600
 Subject: [PATCH] Fix ServerListPingEvent flagging as Async
@@ -50,5 +50,5 @@ index 343f238..3c38d85 100644
          this.address = address;
          this.motd = motd;
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch
similarity index 95%
rename from Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch
rename to Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch
index 68e5a6d74..b5903635e 100644
--- a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch
+++ b/Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch
@@ -1,4 +1,4 @@
-From c86b4710176897c1c3cffa381cc212ff53c0fe4a Mon Sep 17 00:00:00 2001
+From 2f744e6d6116fd4debbba556368e44db6d1b9090 Mon Sep 17 00:00:00 2001
 From: kashike <kashike@vq.lc>
 Date: Tue, 8 Mar 2016 13:05:59 -0800
 Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender
@@ -40,7 +40,7 @@ index 148756b..4ad0028 100644
 +    // Paper end
  }
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 8124c71..b9c9af0 100644
+index 5326ea6..2951b98 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -338,6 +338,7 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
@@ -60,5 +60,5 @@ index 8124c71..b9c9af0 100644
  
      /**
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch
similarity index 93%
rename from Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch
rename to Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch
index 1ae4fdf75..3313ad450 100644
--- a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch
+++ b/Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch
@@ -1,4 +1,4 @@
-From ed0f87d97dc3b1e85e2ef56ba8d6ec1e871df32d Mon Sep 17 00:00:00 2001
+From 578d1f92b19a427d2deb9ded55c699ea9fdbdec4 Mon Sep 17 00:00:00 2001
 From: mrapple <tony@oc.tc>
 Date: Sun, 25 Nov 2012 13:47:27 -0600
 Subject: [PATCH] Add methods for working with arrows stuck in living entities
@@ -29,5 +29,5 @@ index 22de9f7..570da41 100644
 +    // Paper end
  }
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch b/Spigot-API-Patches/0023-Complete-resource-pack-API.patch
similarity index 97%
rename from Spigot-API-Patches/0022-Complete-resource-pack-API.patch
rename to Spigot-API-Patches/0023-Complete-resource-pack-API.patch
index 0eef6f3ab..8eed7d6b1 100644
--- a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch
+++ b/Spigot-API-Patches/0023-Complete-resource-pack-API.patch
@@ -1,11 +1,11 @@
-From fa6a25250e75d5ec7ded2fc985067a64e71e6b0f Mon Sep 17 00:00:00 2001
+From 7b4059b9b56f49f1a227fb39b1ea909245a1203d Mon Sep 17 00:00:00 2001
 From: Jedediah Smith <jedediah@silencegreys.com>
 Date: Sat, 4 Apr 2015 22:59:54 -0400
 Subject: [PATCH] Complete resource pack API
 
 
 diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index b9c9af0..b7496a3 100644
+index 2951b98..d7c8069 100644
 --- a/src/main/java/org/bukkit/entity/Player.java
 +++ b/src/main/java/org/bukkit/entity/Player.java
 @@ -1099,7 +1099,9 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
@@ -110,5 +110,5 @@ index 4c49801..4c83851 100644
       * Gets the status of this pack.
       *
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch
similarity index 99%
rename from Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch
rename to Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch
index 338c2ae3d..01ce28e4a 100644
--- a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch
+++ b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch
@@ -1,4 +1,4 @@
-From c1dc52ffb0997b633a552eb4fc6341de01a50e40 Mon Sep 17 00:00:00 2001
+From e5e95709d29d23cb34387060e95de1aad352e432 Mon Sep 17 00:00:00 2001
 From: Techcable <Techcable@outlook.com>
 Date: Thu, 3 Mar 2016 13:20:33 -0700
 Subject: [PATCH] Use ASM for event executors.
@@ -6,7 +6,7 @@ Subject: [PATCH] Use ASM for event executors.
 Uses method handles for private or static methods.
 
 diff --git a/pom.xml b/pom.xml
-index 0b615b4..1ad108e 100644
+index d3a877a..92a729b 100644
 --- a/pom.xml
 +++ b/pom.xml
 @@ -112,6 +112,12 @@
@@ -395,5 +395,5 @@ index 93a43dd..7229b25 100644
                  eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
              } else {
 -- 
-2.7.2
+2.8.0
 
diff --git a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch b/Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch
similarity index 94%
rename from Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch
rename to Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch
index f6683f702..0419c1611 100644
--- a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch
+++ b/Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch
@@ -1,4 +1,4 @@
-From 82df1be4b32c98bc98852d11792b42808db38322 Mon Sep 17 00:00:00 2001
+From 81c991a2a0e0f1f58a73b49bb276ab52884d433d Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Sun, 19 May 2013 20:36:58 -0400
 Subject: [PATCH] Add a call helper to Event
@@ -40,5 +40,5 @@ index 6677e1b..eaf6c49 100644
       * Convenience method for providing a user-friendly identifier. By
       * default, it is the event's class's {@linkplain Class#getSimpleName()
 -- 
-2.7.3
+2.8.0
 
diff --git a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch b/Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch
similarity index 96%
rename from Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch
rename to Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch
index f81e32ca7..26a3c3334 100644
--- a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch
+++ b/Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch
@@ -1,4 +1,4 @@
-From 69a33cc93b8fdb90057a7cb3a82fddfe61074033 Mon Sep 17 00:00:00 2001
+From 21d5ec9b192521a3502ad03fdc32d217651ab129 Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Wed, 22 Jul 2015 18:50:41 -0400
 Subject: [PATCH] Add sender name to commands.yml replacement
@@ -41,5 +41,5 @@ index f89ad07..a3e9c63 100644
          while (index != -1) {
              int start = index;
 -- 
-2.7.3
+2.8.0
 
diff --git a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch
similarity index 98%
rename from Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch
rename to Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch
index a428a02ef..6a9823c7f 100644
--- a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch
+++ b/Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch
@@ -1,4 +1,4 @@
-From 208b1904b32400b1745e6c89be57fded2d285a60 Mon Sep 17 00:00:00 2001
+From bd8ce76652697575ba15e5efec4710cf0dcd2bba Mon Sep 17 00:00:00 2001
 From: William <admin@domnian.com>
 Date: Fri, 18 Mar 2016 03:28:07 -0400
 Subject: [PATCH] Add command to reload permissions.yml and require confirm to
@@ -102,5 +102,5 @@ index 49f5872..e988a7c 100644
 +
  }
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch b/Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch
similarity index 95%
rename from Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch
rename to Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch
index 9f76655ea..7f275a14a 100644
--- a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch
+++ b/Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch
@@ -1,4 +1,4 @@
-From 11d6fcf537a9f03b483874c2c2dee87a71fe19ca Mon Sep 17 00:00:00 2001
+From 9ffd06f684daada133fc1b90cc983c8598a6e328 Mon Sep 17 00:00:00 2001
 From: Jedediah Smith <jedediah@silencegreys.com>
 Date: Sun, 21 Jun 2015 15:05:21 -0400
 Subject: [PATCH] Custom replacement for eaten items
@@ -42,5 +42,5 @@ index 8ab76b1..42aad88 100644
          return this.isCancelled;
      }
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch b/Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch
similarity index 93%
rename from Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch
rename to Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch
index 50ce81d30..79eb54524 100644
--- a/Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch
+++ b/Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch
@@ -1,4 +1,4 @@
-From df17741c376cfdac8301e64a9dc9a956e75ae5f1 Mon Sep 17 00:00:00 2001
+From 0024ceed3f1fac5330f4bafd0054f54229489089 Mon Sep 17 00:00:00 2001
 From: Jedediah Smith <jedediah@silencegreys.com>
 Date: Sun, 20 Mar 2016 06:44:49 -0400
 Subject: [PATCH] Access items by EquipmentSlot
@@ -32,5 +32,5 @@ index 557cc04..799f150 100644
 +    // Paper end
  }
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch
similarity index 97%
rename from Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch
rename to Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch
index 7bc9059f0..5120a0ad7 100644
--- a/Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch
+++ b/Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch
@@ -1,4 +1,4 @@
-From 6fbe0184aa41dd325adc6415b01dda65b1b97c35 Mon Sep 17 00:00:00 2001
+From d32bff844b27d2b2e5827728d21411630c15d25e Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 28 Mar 2016 20:26:34 -0400
 Subject: [PATCH] Entity AddTo/RemoveFrom World Events
@@ -88,5 +88,5 @@ index 0000000..9b522ce
 +    }
 +}
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0030-EntityPathfindEvent.patch b/Spigot-API-Patches/0031-EntityPathfindEvent.patch
similarity index 97%
rename from Spigot-API-Patches/0030-EntityPathfindEvent.patch
rename to Spigot-API-Patches/0031-EntityPathfindEvent.patch
index 1b037fb45..9e46fdede 100644
--- a/Spigot-API-Patches/0030-EntityPathfindEvent.patch
+++ b/Spigot-API-Patches/0031-EntityPathfindEvent.patch
@@ -1,4 +1,4 @@
-From 973cff5bb740f213b5a90297c9cd132e4a57d8e4 Mon Sep 17 00:00:00 2001
+From 0cbfd3f956fe731e9a2c1e0838afd8cb577e338b Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Mon, 28 Mar 2016 21:15:34 -0400
 Subject: [PATCH] EntityPathfindEvent
@@ -87,5 +87,5 @@ index 0000000..21cab26
 +    }
 +}
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch
similarity index 98%
rename from Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch
rename to Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch
index f4c34be9d..c30f4d4b5 100644
--- a/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch
+++ b/Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch
@@ -1,4 +1,4 @@
-From d8fc6b74a4f590473b3abad8958d0e929df6074f Mon Sep 17 00:00:00 2001
+From dd1173b521819609b5a9625b4da4a464ef403db7 Mon Sep 17 00:00:00 2001
 From: crast <contact@jamescrasta.com>
 Date: Sat, 1 Jun 2013 13:52:30 -0600
 Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase
@@ -101,5 +101,5 @@ index 093c144..64c0f0a 100644
          for (Map<Plugin, MetadataValue> values : metadataMap.values()) {
              if (values.containsKey(owningPlugin)) {
 -- 
-2.7.4
+2.8.0
 
diff --git a/Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch b/Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch
similarity index 95%
rename from Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch
rename to Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch
index 90d4b4f81..4d229d2ce 100644
--- a/Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch
+++ b/Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch
@@ -1,4 +1,4 @@
-From 9bfe42cfc7f02966926c3dccc68b7dc85e3c25cc Mon Sep 17 00:00:00 2001
+From 61a2f66cc4b6f90f0488d5f4f7df76153ddbbaf9 Mon Sep 17 00:00:00 2001
 From: Aikar <aikar@aikar.co>
 Date: Tue, 16 Jul 2013 21:26:50 -0400
 Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin)
@@ -37,5 +37,5 @@ index 64c0f0a..6da6abd 100644
       * unique data from the subject with a metadataKey.
       * <p>
 -- 
-2.7.4
+2.8.0