From c92ce02363328aa607287a6b92c62d2d74b17764 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 1 Apr 2016 00:18:18 -0400 Subject: [PATCH] Move fastutil from a patch file to a library, and improve EAR --- ...-fastutil-int-long-based-collections.patch | 45211 ---------------- ...002-add-Trove-and-FastUtil-to-Bukkit.patch | 33 + Spigot-API-Patches/0003-Timings-v2.patch | 25 +- .../0024-Use-ASM-for-event-executors.patch | 6 +- Spigot-Server-Patches/0005-Timings-v2.patch | 19 +- ...AR-Fix-bug-with-teleporting-entities.patch | 15 +- pom.xml | 6 +- 7 files changed, 74 insertions(+), 45241 deletions(-) delete mode 100644 Spigot-API-Patches/0002-Add-minimal-fastutil-int-long-based-collections.patch create mode 100644 Spigot-API-Patches/0002-add-Trove-and-FastUtil-to-Bukkit.patch diff --git a/Spigot-API-Patches/0002-Add-minimal-fastutil-int-long-based-collections.patch b/Spigot-API-Patches/0002-Add-minimal-fastutil-int-long-based-collections.patch deleted file mode 100644 index 351af959c..000000000 --- a/Spigot-API-Patches/0002-Add-minimal-fastutil-int-long-based-collections.patch +++ /dev/null @@ -1,45211 +0,0 @@ -From bc17a29787a7d9c927d9812b74db623b9ca066b2 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Mon, 21 Mar 2016 18:17:14 -0400 -Subject: [PATCH] Add minimal fastutil int/long based collections - -Importing entire FastUtil library would be massive. Just import minimal useful ones -we might actually use. - -diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java -new file mode 100644 -index 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. -+ * -+ *

This class defines {@link #secondaryLast()} as throwing an -+ * {@link UnsupportedOperationException}. -+ */ -+ -+public abstract class AbstractIndirectDoublePriorityQueue extends AbstractIndirectPriorityQueue implements IndirectDoublePriorityQueue { -+ -+ 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. -+ * -+ *

This class defines {@link #changed(int)}, {@link #allChanged()}, {@link #remove(int)} and {@link #last()} as throwing an -+ * {@link UnsupportedOperationException}. -+ */ -+ -+public abstract class AbstractIndirectPriorityQueue implements IndirectPriorityQueue { -+ -+ 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. -+ * -+ *

This class defines {@link #changed()} and {@link #last()} as throwing an -+ * {@link UnsupportedOperationException}. -+ */ -+ -+public abstract class AbstractPriorityQueue implements PriorityQueue { -+ -+ 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. -+ * -+ *

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 implements Stack { -+ -+ 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. -+ * -+ *

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. -+ * -+ *

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 from is greater than to. -+ * @throws ArrayIndexOutOfBoundsException if from or to are greater than arrayLength 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. -+ * -+ *

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 length is negative. -+ * @throws ArrayIndexOutOfBoundsException if offset is negative or offset+length is greater than arrayLength. -+ */ -+ 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 -+ * [first..middle) and [middle..last), and the resulting range is -+ * [first..last). 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 [first..i), -+ * comp.compare(j, pos) is true. -+ */ -+ 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 [first..i), -+ * comp.compare(pos, j) is false. -+ */ -+ 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. -+ * -+ *

This sort is guaranteed to be stable: 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 O(n (log n)2), 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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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}. -+ * -+ *

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. -+ * -+ *

Note that iterators returned by fastutil 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 extends Iterator { -+ -+ /** 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. -+ * -+ *

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. -+ * -+ *

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). -+ * -+ *

Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction} that -+ * can also set its default return value. -+ * -+ *

Warning: Equality of functions is not specified -+ * by contract, and it will usually be by reference, 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 { -+ -+ /** 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 null 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 null 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. -+ * -+ *

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 key. -+ * @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 null 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. -+ * -+ *

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. -+ * -+ *

Historical note

-+ * -+ *

Warning: the following comments are here for historical reasons, -+ * and apply just to the double hash classes that can be optionally generated. -+ * The standard fastutil distribution since 6.1.0 uses linear-probing hash -+ * tables, and tables are always sized as powers of two. -+ * -+ *

The classes in fastutil are built around open-addressing hashing -+ * implemented via double hashing. Following Knuth's suggestions in the third volume of The Art of Computer -+ * Programming, we use for the table size a prime p such that -+ * p-2 is also prime. In this way hashing is implemented with modulo p, -+ * and secondary hashing with modulo p-2. -+ * -+ *

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, -+ * fastutil implements two useful optimizations, based on the following invariant: -+ *

-+ * Let i0, i1, …, ip-1 be -+ * the permutation of the table indices induced by the key k, that is, i0 is the hash -+ * of k and the following indices are obtained by adding (modulo p) the secondary hash plus one. -+ * If there is a {@link #OCCUPIED} entry with key k, its index in the sequence above comes before -+ * the indices of any {@link #REMOVED} entries with key k. -+ *
-+ * -+ *

When we search for the key k we scan the entries in the -+ * sequence i0, i1, …, -+ * ip-1 and stop when k 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 k 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). -+ * -+ *

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 -+ * a fortiori 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. -+ * -+ *

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 hash strategy, 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. -+ * -+ *

Note that the {@link #equals(Object,Object) equals()} method of a strategy must -+ * be able to handle null, too. -+ */ -+ -+ public interface Strategy { -+ -+ /** Returns the hash code of the specified object with respect to this hash strategy. -+ * -+ * @param o an object (or null). -+ * @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 null). -+ * @param b another object (or null). -+ * @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 i-th element is -+ * the largest prime p smaller than 2(i+28)/16 -+ * and such that p-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). null cannot be used as it would confuse the -+ search algorithm in the presence of an actual null key. */ -+ public static final Object REMOVED = new Object(); -+ -+ /** 232 · φ, φ = (√5 − 1)/2. */ -+ private static final int INT_PHI = 0x9E3779B9; -+ /** The reciprocal of {@link #INT_PHI} modulo 232. */ -+ private static final int INV_INT_PHI = 0x144cbc89; -+ /** 264 · φ, φ = (√5 − 1)/2. */ -+ private static final long LONG_PHI = 0x9E3779B97F4A7C15L; -+ /** The reciprocal of {@link #LONG_PHI} modulo 264. */ -+ private static final long INV_LONG_PHI = 0xf1de83e19937733dL; -+ -+ /** Avalanches the bits of an integer by applying the finalisation step of MurmurHash3. -+ * -+ *

This method implements the finalisation step of Austin Appleby's MurmurHash3. -+ * 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. -+ * -+ *

This method implements the finalisation step of Austin Appleby's MurmurHash3. -+ * 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. -+ * -+ *

This method mixes the bits of the argument by multiplying by the golden ratio and -+ * xorshifting the result. It is borrowed from Koloboke, 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. -+ * -+ *

This method mixes the bits of the argument by multiplying by the golden ratio and -+ * xorshifting twice the result. It is borrowed from Koloboke, 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. -+ * -+ *

Note that this function will return 1 when the argument is 0. -+ * -+ * @param x an integer smaller than or equal to 230. -+ * @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. -+ * -+ *

Note that this function will return 1 when the argument is 0. -+ * -+ * @param x a long integer smaller than or equal to 262. -+ * @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 230 and larger than or equal to Math.ceil( expected / f ). -+ * -+ * @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 230. -+ */ -+ 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 Math.ceil( expected / f ). -+ * -+ * @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. -+ * -+ *

An indirect double priority queue uses two distinct comparators (called primary -+ * and secondary) 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 extends IndirectPriorityQueue { -+ -+ /** Returns the secondary comparator of this queue. -+ * -+ * @return the secondary comparator of this queue. -+ * @see #secondaryFirst() -+ */ -+ public Comparator 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 a). -+ * @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. -+ * -+ *

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 implements IndirectDoublePriorityQueue { -+ -+ public static final long serialVersionUID = -7046029254386353129L; -+ -+ final protected IndirectDoublePriorityQueue q; -+ final protected Object sync; -+ -+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue q, final Object sync ) { -+ this.q = q; -+ this.sync = sync; -+ } -+ -+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue 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 comparator() { synchronized( sync ) { return q.comparator(); } } -+ public Comparator 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 IndirectDoublePriorityQueue synchronize( final IndirectDoublePriorityQueue q ) { return new SynchronizedIndirectDoublePriorityQueue( 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 IndirectDoublePriorityQueue synchronize( final IndirectDoublePriorityQueue q, final Object sync ) { return new SynchronizedIndirectDoublePriorityQueue( 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. -+ * -+ *

An indirect priority queue provides a way to {@linkplain #enqueue(int) -+ * enqueue} by index elements taken from a given reference list, -+ * and to {@linkplain #dequeue() dequeue} them in some specified order. -+ * Elements that are smaller 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. -+ * -+ *

Additionally, the queue may provide a method to peek at the index of the -+ * element that would be dequeued {@linkplain #last() last}. -+ * -+ *

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}. -+ * -+ *

Optionally, an indirect priority queue may even provide methods to notify -+ * {@linkplain #changed(int) the change of any 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}. -+ * -+ *

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. -+ * -+ *

Note that all element manipulation happens via indices. -+ */ -+ -+public interface IndirectPriorityQueue { -+ -+ /** 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 null if it uses its elements' natural ordering. -+ * -+ * @return the comparator associated with this sorted set, or null if it uses its elements' natural ordering. -+ */ -+ Comparator comparator(); -+ -+ /** Notifies this queue that the specified element has changed (optional operation). -+ * -+ *

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). -+ * -+ *

The front 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 a). -+ */ -+ -+ 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. -+ * -+ *

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 implements IndirectPriorityQueue { -+ -+ public static final long serialVersionUID = -7046029254386353129L; -+ -+ final protected IndirectPriorityQueue q; -+ final protected Object sync; -+ -+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue q, final Object sync ) { -+ this.q = q; -+ this.sync = sync; -+ } -+ -+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue 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 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 IndirectPriorityQueue synchronize( final IndirectPriorityQueue q ) { return new SynchronizedIndirectPriorityQueue( 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 IndirectPriorityQueue synchronize( final IndirectPriorityQueue q, final Object sync ) { return new SynchronizedIndirectPriorityQueue( 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 null 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. -+ * -+ *

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 smaller 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. -+ * -+ *

Additionally, the queue may provide a method to peek at -+ * element that would be dequeued {@linkplain #last() last}. -+ * -+ *

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 { -+ -+ /** 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 null if it uses its elements' natural ordering. -+ * -+ * @return the comparator associated with this sorted set, or null if it uses its elements' natural ordering. -+ */ -+ Comparator 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. -+ * -+ *

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 implements PriorityQueue { -+ -+ public static final long serialVersionUID = -7046029254386353129L; -+ -+ final protected PriorityQueue q; -+ final protected Object sync; -+ -+ protected SynchronizedPriorityQueue( final PriorityQueue q, final Object sync ) { -+ this.q = q; -+ this.sync = sync; -+ } -+ -+ protected SynchronizedPriorityQueue( final PriorityQueue 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 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 PriorityQueue synchronize( final PriorityQueue q ) { return new SynchronizedPriorityQueue( 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 PriorityQueue synchronize( final PriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( 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}. -+ * -+ *

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 instanceof to check for the presence of {@link #size64()}. -+ * -+ *

We remark that it is always a good idea to implement both {@link #size()} and {@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 deprecated method returning Math.min(Integer.MAX_VALUE, size64()). -+ */ -+ -+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. -+ * -+ *

A stack must provide the classical {@link #push(Object)} and -+ * {@link #pop()} operations, but may be also peekable -+ * 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 { -+ -+ /** 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 i-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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null on a missing key). -+ * -+ *

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 -+ * defRetValue to denote lack of a key in type-specific methods. The value -+ * is serialized. -+ * -+ *

Implementing subclasses have just to provide type-specific get(), -+ * type-specific containsKey(), and size() methods. -+ * -+ */ -+public abstract class AbstractInt2ObjectFunction implements Int2ObjectFunction , java.io.Serializable { -+ private static final long serialVersionUID = -4940583368468432370L; -+ protected AbstractInt2ObjectFunction() {} -+ /** -+ * The default return value for get(), put() and -+ * remove(). -+ */ -+ 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null on a missing key). -+ * -+ *

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 extends AbstractInt2ObjectFunction implements Int2ObjectMap , 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 m) { -+ int n = m.size(); -+ final Iterator> i = m.entrySet().iterator(); -+ if (m instanceof Int2ObjectMap) { -+ Int2ObjectMap.Entry e; -+ while(n-- != 0) { -+ e = (Int2ObjectMap.Entry )i.next(); -+ put(e.getIntKey(), e.getValue()); -+ } -+ } -+ else { -+ Map.Entry 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). -+ * -+ *

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 implements Int2ObjectMap.Entry { -+ 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. -+ * -+ *

The view is backed by the set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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> i = entrySet().iterator(); -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public int nextInt() { return ((Int2ObjectMap.Entry )i.next()).getIntKey(); }; -+ public boolean hasNext() { return i.hasNext(); } -+ }; -+ } -+ }; -+ } -+ /** Returns a type-specific-set view of the values of this map. -+ * -+ *

The view is backed by the set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 values() { -+ return new AbstractObjectCollection () { -+ public boolean contains( final Object k ) { return containsValue( k ); } -+ public int size() { return AbstractInt2ObjectMap.this.size(); } -+ public void clear() { AbstractInt2ObjectMap.this.clear(); } -+ public ObjectIterator iterator() { -+ return new AbstractObjectIterator () { -+ final ObjectIterator> i = entrySet().iterator(); -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public V next() { return ((Int2ObjectMap.Entry )i.next()).getValue(); }; -+ public boolean hasNext() { return i.hasNext(); } -+ }; -+ } -+ }; -+ } -+ @SuppressWarnings({ "unchecked", "rawtypes" }) -+ public ObjectSet> 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> 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> i = entrySet().iterator(); -+ int n = size(); -+ Int2ObjectMap.Entry e; -+ boolean first = true; -+ s.append("{"); -+ while(n-- != 0) { -+ if (first) first = false; -+ else s.append(", "); -+ e = (Int2ObjectMap.Entry )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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends AbstractInt2ObjectMap implements Int2ObjectSortedMap { -+ 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 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 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 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. -+ * -+ *

The view is backed by the sorted set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 ( entrySet().iterator( new BasicEntry ( from, (null) ) ) ); } -+ public IntBidirectionalIterator iterator() { return new KeySetIterator ( entrySet().iterator() ); } -+ } -+ /** A wrapper exhibiting a map iterator as an iterator on keys. -+ * -+ *

To provide an iterator on keys, just create an instance of this -+ * class using the corresponding iterator on entries. -+ */ -+ protected static class KeySetIterator extends AbstractIntBidirectionalIterator { -+ protected final ObjectBidirectionalIterator> i; -+ public KeySetIterator( ObjectBidirectionalIterator> 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. -+ * -+ *

The view is backed by the sorted set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 values() { -+ return new ValuesCollection(); -+ } -+ /** A wrapper exhibiting the values of a map. */ -+ protected class ValuesCollection extends AbstractObjectCollection { -+ public ObjectIterator iterator() { return new ValuesIterator ( 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. -+ * -+ *

To provide an iterator on values, just create an instance of this -+ * class using the corresponding iterator on entries. -+ */ -+ protected static class ValuesIterator extends AbstractObjectIterator { -+ protected final ObjectBidirectionalIterator> i; -+ public ValuesIterator( ObjectBidirectionalIterator> i ) { -+ this.i = i; -+ } -+ public V next() { return (i.next().getValue()); }; -+ public boolean hasNext() { return i.hasNext(); } -+ } -+ @SuppressWarnings({ "unchecked", "rawtypes" }) -+ public ObjectSortedSet> 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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). -+ * -+ *

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 n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

In particular, this class provide {@link #iterator()}, add(), {@link #remove(Object)} and -+ * {@link #contains(Object)} methods that just call the type-specific counterpart. -+ */ -+public abstract class AbstractIntCollection extends AbstractCollection 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 true 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 true 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 true 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 true 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[] 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 true if this collection changed as a result of the call. -+ */ -+ public boolean addAll( Collection c ) { -+ boolean retVal = false; -+ final Iterator 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 rem() 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 true 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 true 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 true 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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). -+ * -+ *

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 -+ * n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 c ) { -+ ensureIndex( index ); -+ int n = c.size(); -+ if ( n == 0 ) return false; -+ Iterator i = c.iterator(); -+ while( n-- != 0 ) add( index++, i.next() ); -+ return true; -+ } -+ /** Delegates to a more generic method. */ -+ public boolean addAll( final Collection 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 ClassCastException. -+ * -+ * @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 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 i1 = listIterator(), i2 = l.listIterator(); -+ int r; -+ while( i1.hasNext() && i2.hasNext() ) { -+ if ( ( r = ((Comparable)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 rem(). */ -+ 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)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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 remove(). -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 iterator() can be safely cast -+ * to a type-specific {@linkplain java.util.ListIterator list iterator}. -+ */ -+public class Int2ObjectAVLTreeMap extends AbstractInt2ObjectSortedMap implements java.io.Serializable, Cloneable { -+ /** A reference to the root entry. */ -+ protected transient Entry tree; -+ /** Number of entries in this map. */ -+ protected int count; -+ /** The first key in this map. */ -+ protected transient Entry firstEntry; -+ /** The last key in this map. */ -+ protected transient Entry lastEntry; -+ /** Cached set of entries. */ -+ protected transient ObjectSortedSet > entries; -+ /** Cached set of keys. */ -+ protected transient IntSortedSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** The value of this variable remembers, after a put() -+ * or a remove(), whether the domain of the map -+ * has been modified. */ -+ protected transient boolean modified; -+ /** This map's comparator, as provided in the constructor. */ -+ protected Comparator 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. -+ * -+ *

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 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 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 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 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 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 k and v have different lengths. -+ */ -+ public Int2ObjectAVLTreeMap( final int[] k, final V v[], final Comparator 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 k and v 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. -+ * -+ *

This method uses the {@link #actualComparator} if it is non-null. -+ * 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 < k2, k1 = k2 or k1 > 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; null, otherwise. -+ * -+ * @param k the key to search for. -+ * @return the corresponding entry, or null if no entry with the given key exists. -+ */ -+ final Entry findKey( final int k ) { -+ Entry 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 locateKey( final int k ) { -+ Entry 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 232 entries. */ -+ private transient boolean dirPath[]; -+ private void allocatePaths() { -+ dirPath = new boolean[ 48 ]; -+ } -+ public V put( final int k, final V v ) { -+ Entry 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 add( final int k ) { -+ /* After execution of this method, modified is true iff a new entry has -+ been inserted. */ -+ modified = false; -+ Entry e = null; -+ if ( tree == null ) { // The case of the empty tree is treated separately. -+ count++; -+ e = tree = lastEntry = firstEntry = new Entry ( k, defRetValue ); -+ modified = true; -+ } -+ else { -+ Entry 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 ( 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 ( 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 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 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 null for the root. -+ */ -+ private Entry parent( final Entry e ) { -+ if ( e == tree ) return null; -+ Entry 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 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 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 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 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 x = y.right; -+ if ( ASSERTS ) assert x != null; -+ if ( x.balance() == -1 ) { -+ Entry 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 x = y.left; -+ if ( ASSERTS ) assert x != null; -+ if ( x.balance() == 1 ) { -+ Entry 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. -+ * -+ *

We use the only "metadata", i.e., {@link Entry#info}, to store -+ * information about balance, predecessor status and successor status. -+ * -+ *

Note that since the class is recursive, it can be -+ * considered equivalently a tree. -+ */ -+ private static final class Entry implements Cloneable, Int2ObjectMap.Entry { -+ /** 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 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 (null if the left -+ * subtree is empty). -+ */ -+ Entry left() { -+ return ( info & PRED_MASK ) != 0 ? null : left; -+ } -+ /** Returns the right subtree. -+ * -+ * @return the right subtree (null if the right -+ * subtree is empty). -+ */ -+ Entry 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 pred ) { -+ info |= PRED_MASK; -+ left = pred; -+ } -+ /** Sets the right pointer to a successor. -+ * @param succ the successor. -+ */ -+ void succ( final Entry succ ) { -+ info |= SUCC_MASK; -+ right = succ; -+ } -+ /** Sets the left pointer to the given subtree. -+ * @param left the new left subtree. -+ */ -+ void left( final Entry 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 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 (null) if this is the last entry). -+ */ -+ Entry next() { -+ Entry 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 (null) if this is the first entry). -+ */ -+ Entry prev() { -+ Entry 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 clone() { -+ Entry c; -+ try { -+ c = (Entry )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 e = (Map.Entry)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 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. -+ * -+ *

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 null if no previous entry exists). */ -+ Entry prev; -+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or null if no next entry exists). */ -+ Entry next; -+ /** The last entry that was returned (or null if we did not iterate or used {@link #remove()}). */ -+ Entry 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 nextEntry() { -+ if ( ! hasNext() ) throw new NoSuchElementException(); -+ curr = prev = next; -+ index++; -+ updateNext(); -+ return curr; -+ } -+ void updatePrevious() { -+ prev = prev.prev(); -+ } -+ Entry 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. -+ * -+ *

This class can iterate in both directions on a threaded tree. -+ */ -+ private class EntryIterator extends TreeIterator implements ObjectListIterator > { -+ EntryIterator() {} -+ EntryIterator( final int k ) { -+ super( k ); -+ } -+ public Int2ObjectMap.Entry next() { return nextEntry(); } -+ public Int2ObjectMap.Entry previous() { return previousEntry(); } -+ public void set( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ public ObjectSortedSet > int2ObjectEntrySet() { -+ if ( entries == null ) entries = new AbstractObjectSortedSet >() { -+ final Comparator > comparator = new Comparator > () { -+ public int compare( final Int2ObjectMap.Entry x, final Int2ObjectMap.Entry y ) { -+ return Int2ObjectAVLTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() ); -+ } -+ }; -+ public Comparator > comparator() { -+ return comparator; -+ } -+ public ObjectBidirectionalIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectBidirectionalIterator > iterator( final Int2ObjectMap.Entry from ) { -+ return new EntryIterator( from.getIntKey() ); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if (!(o instanceof Map.Entry)) return false; -+ final Map.Entry e = (Map.Entry )o; -+ if ( e.getKey() == null ) return false; -+ final Entry 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 e = (Map.Entry )o; -+ if ( e.getKey() == null ) return false; -+ final Entry 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 first() { return firstEntry; } -+ public Int2ObjectMap.Entry last() { return lastEntry; } -+ public ObjectSortedSet > subSet( Int2ObjectMap.Entry from, Int2ObjectMap.Entry to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > headSet( Int2ObjectMap.Entry to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > tailSet( Int2ObjectMap.Entry from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); } -+ }; -+ return entries; -+ } -+ /** An iterator on the whole range of keys. -+ * -+ *

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 .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. -+ * -+ *

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. -+ * -+ *

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 { -+ 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. -+ * -+ *

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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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 headMap( int to ) { -+ return new Submap( (0), true, to, false ); -+ } -+ public Int2ObjectSortedMap tailMap( int from ) { -+ return new Submap( from, false, (0), true ); -+ } -+ public Int2ObjectSortedMap subMap( int from, int to ) { -+ return new Submap( from, false, to, false ); -+ } -+ /** A submap with given range. -+ * -+ *

This class represents a submap. One has to specify the left/right -+ * limits (which can be set to -∞ or ∞). 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 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 -∞. */ -+ boolean bottom; -+ /** If true, the submap range goes to ∞. */ -+ boolean top; -+ /** Cached set of entries. */ -+ @SuppressWarnings("hiding") -+ protected transient ObjectSortedSet > entries; -+ /** Cached set of keys. */ -+ @SuppressWarnings("hiding") -+ protected transient IntSortedSet keys; -+ /** Cached collection of values. */ -+ @SuppressWarnings("hiding") -+ protected transient ObjectCollection 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 -∞. -+ * @param to the end of the submap range. -+ * @param top if true, the third parameter is ignored and the range goes to ∞. -+ */ -+ 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 > int2ObjectEntrySet() { -+ if ( entries == null ) entries = new AbstractObjectSortedSet >() { -+ public ObjectBidirectionalIterator > iterator() { -+ return new SubmapEntryIterator(); -+ } -+ public ObjectBidirectionalIterator > iterator( final Int2ObjectMap.Entry from ) { -+ return new SubmapEntryIterator( from.getIntKey() ); -+ } -+ public Comparator > comparator() { return Int2ObjectAVLTreeMap.this.entrySet().comparator(); } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if (!(o instanceof Map.Entry)) return false; -+ final Map.Entry e = (Map.Entry )o; -+ final Int2ObjectAVLTreeMap.Entry 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 e = (Map.Entry )o; -+ final Int2ObjectAVLTreeMap.Entry 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 first() { return firstEntry(); } -+ public Int2ObjectMap.Entry last() { return lastEntry(); } -+ public ObjectSortedSet > subSet( Int2ObjectMap.Entry from, Int2ObjectMap.Entry to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > headSet( Int2ObjectMap.Entry to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > tailSet( Int2ObjectMap.Entry from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); } -+ }; -+ return entries; -+ } -+ private class KeySet extends AbstractInt2ObjectSortedMap .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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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 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 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 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 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 null if the submap is empty. -+ */ -+ public Int2ObjectAVLTreeMap.Entry 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 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 null if the submap is empty. -+ */ -+ public Int2ObjectAVLTreeMap.Entry 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 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 e = firstEntry(); -+ if ( e == null ) throw new NoSuchElementException(); -+ return e.key; -+ } -+ public int lastIntKey() { -+ Int2ObjectAVLTreeMap.Entry 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 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 e = lastEntry(); -+ if ( e == null ) throw new NoSuchElementException(); -+ return e.getKey(); -+ } -+ /** An iterator for subranges. -+ * -+ *

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 null. -+ */ -+ 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 > { -+ SubmapEntryIterator() {} -+ SubmapEntryIterator( final int k ) { -+ super( k ); -+ } -+ public Int2ObjectMap.Entry next() { return nextEntry(); } -+ public Int2ObjectMap.Entry previous() { return previousEntry(); } -+ public void set( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ /** An iterator on a subrange of keys. -+ * -+ *

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. -+ * -+ *

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 { -+ 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. -+ * -+ *

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 clone() { -+ Int2ObjectAVLTreeMap c; -+ try { -+ c = (Int2ObjectAVLTreeMap )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 e, p, q, rp = new Entry (), rq = new Entry (); -+ 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 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 readTree( final java.io.ObjectInputStream s, final int n, final Entry pred, final Entry succ ) throws java.io.IOException, ClassNotFoundException { -+ if ( n == 1 ) { -+ final Entry top = new Entry ( 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 top = new Entry ( s.readInt(), (V) s.readObject() ); -+ top.right( new Entry ( 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 top = new Entry (); -+ 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 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 int checkTree( @SuppressWarnings("unused") Entry 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends AbstractInt2ObjectMap 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. -+ * -+ *

It is responsibility of the caller that the elements of key are distinct. -+ * -+ * @param key the key array. -+ * @param value the value array (it must have the same length as key). -+ */ -+ 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 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 m ) { -+ this( m.size() ); -+ putAll( m ); -+ } -+ /** Creates a new array map with given key and value backing arrays, using the given number of elements. -+ * -+ *

It is responsibility of the caller that the first size elements of key are distinct. -+ * -+ * @param key the key array. -+ * @param value the value array (it must have the same length as key). -+ * @param size the number of valid elements in key and value. -+ */ -+ 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 > implements FastEntrySet { -+ @Override -+ public ObjectIterator > iterator() { -+ return new AbstractObjectIterator >() { -+ int curr = -1, next = 0; -+ public boolean hasNext() { -+ return next < size; -+ } -+ @SuppressWarnings("unchecked") -+ public Entry next() { -+ if ( ! hasNext() ) throw new NoSuchElementException(); -+ return new AbstractInt2ObjectMap.BasicEntry ( 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 > fastIterator() { -+ return new AbstractObjectIterator >() { -+ int next = 0, curr = -1; -+ final BasicEntry entry = new BasicEntry ( (0), (null) ); -+ public boolean hasNext() { -+ return next < size; -+ } -+ @SuppressWarnings("unchecked") -+ public Entry 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 e = (Map.Entry)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 e = (Map.Entry)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 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 values() { -+ return ObjectCollections.unmodifiable( new ObjectArraySet ( value, size ) ); -+ } -+ /** Returns a deep copy of this map. -+ * -+ *

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 clone() { -+ Int2ObjectArrayMap c; -+ try { -+ c = (Int2ObjectArrayMap )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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Type-specific versions of get(), put() and -+ * remove() cannot rely on null 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 (false -+ * for booleans) at creation, but can be changed using the -+ * defaultReturnValue() method. -+ * -+ *

For uniformity reasons, even maps returning objects implement the default -+ * return value (of course, in this case the default return value is -+ * initialized to null). -+ * -+ *

Warning: 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 get(), put() and -+ * remove() for maps with primitive-type values return -+ * null to denote missing keys 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 extends Function { -+ /** 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 -+ * get(), put() and remove() to -+ * denote that the map does not contain the specified key. It must be -+ * 0/false/null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific function. -+ */ -+ public static class EmptyFunction extends AbstractInt2ObjectFunction 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific function. -+ */ -+ public static class Singleton extends AbstractInt2ObjectFunction 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectFunction singleton( final int key, V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectFunction singleton( final Integer key, final V value ) { -+ return new Singleton ( ((key).intValue()), (value) ); -+ } -+ /** A synchronized wrapper class for functions. */ -+ public static class SynchronizedFunction extends AbstractInt2ObjectFunction implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectFunction function; -+ protected final Object sync; -+ protected SynchronizedFunction( final Int2ObjectFunction f, final Object sync ) { -+ if ( f == null ) throw new NullPointerException(); -+ this.function = f; -+ this.sync = sync; -+ } -+ protected SynchronizedFunction( final Int2ObjectFunction 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 Int2ObjectFunction synchronize( final Int2ObjectFunction f ) { return new SynchronizedFunction ( 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 Int2ObjectFunction synchronize( final Int2ObjectFunction f, final Object sync ) { return new SynchronizedFunction ( f, sync ); } -+ /** An unmodifiable wrapper class for functions. */ -+ public static class UnmodifiableFunction extends AbstractInt2ObjectFunction implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectFunction function; -+ protected UnmodifiableFunction( final Int2ObjectFunction 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 Int2ObjectFunction unmodifiable( final Int2ObjectFunction f ) { return new UnmodifiableFunction ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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. -+ * -+ *

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 -+ * via an array of longs parallel to the table. -+ * -+ *

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 null. -+ * -+ *

Additional methods, such as getAndMoveToFirst(), make it easy -+ * to use instances of this class as a cache (e.g., with LRU policy). -+ * -+ *

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 which is a key of the map, 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 extends AbstractInt2ObjectSortedMap 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 ((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL). -+ * 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 entries; -+ /** Cached set of keys. */ -+ protected transient IntSortedSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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. -+ *

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 tailMap( int from ) { throw new UnsupportedOperationException(); } -+ public Int2ObjectSortedMap headMap( int to ) { throw new UnsupportedOperationException(); } -+ public Int2ObjectSortedMap subMap( int from, int to ) { throw new UnsupportedOperationException(); } -+ /** A list iterator over a linked map. -+ * -+ *

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 null 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 null 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 > { -+ 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 ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ private class FastEntryIterator extends MapIterator implements ObjectListIterator > { -+ 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 ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ private final class MapEntrySet extends AbstractObjectSortedSet > implements FastSortedEntrySet { -+ public ObjectBidirectionalIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public Comparator > comparator() { return null; } -+ public ObjectSortedSet > subSet( Int2ObjectMap.Entry fromElement, Int2ObjectMap.Entry toElement) { throw new UnsupportedOperationException(); } -+ public ObjectSortedSet > headSet( Int2ObjectMap.Entry toElement ) { throw new UnsupportedOperationException(); } -+ public ObjectSortedSet > tailSet( Int2ObjectMap.Entry fromElement ) { throw new UnsupportedOperationException(); } -+ public Int2ObjectMap.Entry first() { -+ if ( size == 0 ) throw new NoSuchElementException(); -+ return new MapEntry( Int2ObjectLinkedOpenHashMap.this.first ); -+ } -+ public Int2ObjectMap.Entry 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 e = (Map.Entry)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 e = (Map.Entry)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 > iterator( final Int2ObjectMap.Entry from ) { -+ return new EntryIterator( from.getIntKey() ); -+ } -+ public ObjectBidirectionalIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ public ObjectBidirectionalIterator > fastIterator( final Int2ObjectMap.Entry from ) { -+ return new FastEntryIterator( from.getIntKey() ); -+ } -+ } -+ public FastSortedEntrySet int2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ 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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Int2ObjectLinkedOpenHashMap c; -+ try { -+ c = (Int2ObjectLinkedOpenHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 extends Int2ObjectFunction , Map { -+ /** An entry set providing fast iteration. -+ * -+ *

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 fastutil -+ * maps might return {@linkplain #entrySet() entry set} objects of type FastEntrySet: in this case, {@link #fastIterator() fastIterator()} -+ * will return an iterator that is guaranteed not to create a large number of objects, possibly -+ * by returning always the same entry (of course, mutated). -+ */ -+ public interface FastEntrySet extends ObjectSet > { -+ /** 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 > fastIterator(); -+ } -+ /** Returns a set view of the mappings contained in this map. -+ *

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> entrySet(); -+ /** Returns a type-specific set view of the mappings contained in this map. -+ * -+ *

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 > int2ObjectEntrySet(); -+ /** Returns a set view of the keys contained in this map. -+ *

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. -+ *

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 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 extends Map.Entry { -+ /** {@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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific map. -+ */ -+ public static class EmptyMap extends Int2ObjectFunctions.EmptyFunction implements Int2ObjectMap , 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 m ) { throw new UnsupportedOperationException(); } -+ @SuppressWarnings("unchecked") -+ public ObjectSet > int2ObjectEntrySet() { return ObjectSets.EMPTY_SET; } -+ -+ public IntSet keySet() { return IntSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectCollection 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> 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_MAP}. -+ * @return an empty map (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static Int2ObjectMap emptyMap() { -+ return EMPTY_MAP; -+ } -+ /** An immutable class representing a type-specific singleton map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific map. -+ */ -+ public static class Singleton extends Int2ObjectFunctions.Singleton implements Int2ObjectMap , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected transient ObjectSet > entries; -+ protected transient IntSet keys; -+ protected transient ObjectCollection 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 m ) { throw new UnsupportedOperationException(); } -+ public ObjectSet > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Int2ObjectMap.Entry )new SingletonEntry() ); return entries; } -+ public IntSet keySet() { if ( keys == null ) keys = IntSets.singleton( key ); return keys; } -+ public ObjectCollection values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; } -+ protected class SingletonEntry implements Int2ObjectMap.Entry , Map.Entry { -+ /** {@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> 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectMap singleton( final int key, V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectMap singleton( final Integer key, final V value ) { -+ return new Singleton ( ((key).intValue()), (value) ); -+ } -+ /** A synchronized wrapper class for maps. */ -+ public static class SynchronizedMap extends Int2ObjectFunctions.SynchronizedFunction implements Int2ObjectMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectMap map; -+ protected transient ObjectSet > entries; -+ protected transient IntSet keys; -+ protected transient ObjectCollection values; -+ protected SynchronizedMap( final Int2ObjectMap m, final Object sync ) { -+ super( m, sync ); -+ this.map = m; -+ } -+ protected SynchronizedMap( final Int2ObjectMap 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 m ) { synchronized( sync ) { map.putAll( m ); } } -+ public ObjectSet > 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 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> 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 Int2ObjectMap synchronize( final Int2ObjectMap m ) { return new SynchronizedMap ( 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 Int2ObjectMap synchronize( final Int2ObjectMap m, final Object sync ) { return new SynchronizedMap ( m, sync ); } -+ /** An unmodifiable wrapper class for maps. */ -+ public static class UnmodifiableMap extends Int2ObjectFunctions.UnmodifiableFunction implements Int2ObjectMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectMap map; -+ protected transient ObjectSet > entries; -+ protected transient IntSet keys; -+ protected transient ObjectCollection values; -+ protected UnmodifiableMap( final Int2ObjectMap 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 m ) { throw new UnsupportedOperationException(); } -+ public ObjectSet > 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 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> 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 Int2ObjectMap unmodifiable( final Int2ObjectMap m ) { return new UnmodifiableMap ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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 extends AbstractInt2ObjectMap 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 entries; -+ /** Cached set of keys. */ -+ protected transient IntSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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 > { -+ private MapEntry entry; -+ public Int2ObjectMap.Entry 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 > { -+ private final MapEntry entry = new MapEntry(); -+ public MapEntry next() { -+ entry.index = nextEntry(); -+ return entry; -+ } -+ } -+ private final class MapEntrySet extends AbstractObjectSet > implements FastEntrySet { -+ public ObjectIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if ( !( o instanceof Map.Entry ) ) return false; -+ final Map.Entry e = (Map.Entry)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 e = (Map.Entry)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 int2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ public ValueIterator() { super(); } -+ public V next() { return value[ nextEntry() ]; } -+ } -+ public ObjectCollection values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Int2ObjectOpenCustomHashMap c; -+ try { -+ c = (Int2ObjectOpenCustomHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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 extends AbstractInt2ObjectMap 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 entries; -+ /** Cached set of keys. */ -+ protected transient IntSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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 > { -+ private MapEntry entry; -+ public Int2ObjectMap.Entry 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 > { -+ private final MapEntry entry = new MapEntry(); -+ public MapEntry next() { -+ entry.index = nextEntry(); -+ return entry; -+ } -+ } -+ private final class MapEntrySet extends AbstractObjectSet > implements FastEntrySet { -+ public ObjectIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if ( !( o instanceof Map.Entry ) ) return false; -+ final Map.Entry e = (Map.Entry)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 e = (Map.Entry)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 int2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ public ValueIterator() { super(); } -+ public V next() { return value[ nextEntry() ]; } -+ } -+ public ObjectCollection values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Int2ObjectOpenHashMap c; -+ try { -+ c = (Int2ObjectOpenHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 iterator() can be safely cast -+ * to a type-specific {@linkplain java.util.ListIterator list iterator}. -+ * -+ */ -+public class Int2ObjectRBTreeMap extends AbstractInt2ObjectSortedMap implements java.io.Serializable, Cloneable { -+ /** A reference to the root entry. */ -+ protected transient Entry tree; -+ /** Number of entries in this map. */ -+ protected int count; -+ /** The first key in this map. */ -+ protected transient Entry firstEntry; -+ /** The last key in this map. */ -+ protected transient Entry lastEntry; -+ /** Cached set of entries. */ -+ protected transient ObjectSortedSet > entries; -+ /** Cached set of keys. */ -+ protected transient IntSortedSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** The value of this variable remembers, after a put() -+ * or a remove(), whether the domain of the map -+ * has been modified. */ -+ protected transient boolean modified; -+ /** This map's comparator, as provided in the constructor. */ -+ protected Comparator 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. -+ * -+ *

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 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 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 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 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 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 k and v have different lengths. -+ */ -+ public Int2ObjectRBTreeMap( final int[] k, final V v[], final Comparator 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 k and v 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. -+ * -+ *

This method uses the {@link #actualComparator} if it is non-null. -+ * 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 < k2, k1 = k2 or k1 > 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; null, otherwise. -+ * -+ * @param k the key to search for. -+ * @return the corresponding entry, or null if no entry with the given key exists. -+ */ -+ final Entry findKey( final int k ) { -+ Entry 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 locateKey( final int k ) { -+ Entry 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 232 entries. */ -+ private transient boolean dirPath[]; -+ private transient Entry nodePath[]; -+ @SuppressWarnings("unchecked") -+ private void allocatePaths() { -+ dirPath = new boolean[ 64 ]; -+ nodePath = new Entry[ 64 ]; -+ } -+ public V put( final int k, final V v ) { -+ Entry 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 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 e; -+ if ( tree == null ) { // The case of the empty tree is treated separately. -+ count++; -+ e = tree = lastEntry = firstEntry = new Entry ( k, defRetValue ); -+ } -+ else { -+ Entry 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 ( 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 ( 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 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 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 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 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 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 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 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 x = dirPath[ i - 1 ] ? nodePath[ i - 1 ].right : nodePath[ i - 1 ].left; -+ if ( ! x.black() ) { -+ x.black( true ); -+ break; -+ } -+ } -+ if ( ! dirPath[ i - 1 ] ) { -+ Entry 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 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 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 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. -+ * -+ *

We use the only "metadata", i.e., {@link Entry#info}, to store -+ * information about color, predecessor status and successor status. -+ * -+ *

Note that since the class is recursive, it can be -+ * considered equivalently a tree. -+ */ -+ private static final class Entry implements Cloneable, Int2ObjectMap.Entry { -+ /** 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 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 (null if the left -+ * subtree is empty). -+ */ -+ Entry left() { -+ return ( info & PRED_MASK ) != 0 ? null : left; -+ } -+ /** Returns the right subtree. -+ * -+ * @return the right subtree (null if the right -+ * subtree is empty). -+ */ -+ Entry 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 pred ) { -+ info |= PRED_MASK; -+ left = pred; -+ } -+ /** Sets the right pointer to a successor. -+ * @param succ the successor. -+ */ -+ void succ( final Entry succ ) { -+ info |= SUCC_MASK; -+ right = succ; -+ } -+ /** Sets the left pointer to the given subtree. -+ * @param left the new left subtree. -+ */ -+ void left( final Entry 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 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 (null) if this is the last entry). -+ */ -+ Entry next() { -+ Entry 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 (null) if this is the first entry). -+ */ -+ Entry prev() { -+ Entry 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 clone() { -+ Entry c; -+ try { -+ c = (Entry )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 e = (Map.Entry )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 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. -+ * -+ *

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 null if no previous entry exists). */ -+ Entry prev; -+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or null if no next entry exists). */ -+ Entry next; -+ /** The last entry that was returned (or null if we did not iterate or used {@link #remove()}). */ -+ Entry 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 nextEntry() { -+ if ( ! hasNext() ) throw new NoSuchElementException(); -+ curr = prev = next; -+ index++; -+ updateNext(); -+ return curr; -+ } -+ void updatePrevious() { -+ prev = prev.prev(); -+ } -+ Entry 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. -+ * -+ *

This class can iterate in both directions on a threaded tree. -+ */ -+ private class EntryIterator extends TreeIterator implements ObjectListIterator > { -+ EntryIterator() {} -+ EntryIterator( final int k ) { -+ super( k ); -+ } -+ public Int2ObjectMap.Entry next() { return nextEntry(); } -+ public Int2ObjectMap.Entry previous() { return previousEntry(); } -+ public void set( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ public ObjectSortedSet > int2ObjectEntrySet() { -+ if ( entries == null ) entries = new AbstractObjectSortedSet >() { -+ final Comparator > comparator = new Comparator > () { -+ public int compare( final Int2ObjectMap.Entry x, Int2ObjectMap.Entry y ) { -+ return Int2ObjectRBTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() ); -+ } -+ }; -+ public Comparator > comparator() { -+ return comparator; -+ } -+ public ObjectBidirectionalIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectBidirectionalIterator > iterator( final Int2ObjectMap.Entry from ) { -+ return new EntryIterator( from.getIntKey() ); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if (!(o instanceof Map.Entry)) return false; -+ final Map.Entry e = (Map.Entry)o; -+ if ( e.getKey() == null ) return false; -+ final Entry 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 e = (Map.Entry)o; -+ if ( e.getKey() == null ) return false; -+ final Entry 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 first() { return firstEntry; } -+ public Int2ObjectMap.Entry last() { return lastEntry; } -+ public ObjectSortedSet > subSet( Int2ObjectMap.Entry from, Int2ObjectMap.Entry to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > headSet( Int2ObjectMap.Entry to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > tailSet( Int2ObjectMap.Entry from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); } -+ }; -+ return entries; -+ } -+ /** An iterator on the whole range of keys. -+ * -+ *

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 .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. -+ * -+ *

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. -+ * -+ *

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 { -+ 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. -+ * -+ *

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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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 headMap( int to ) { -+ return new Submap( (0), true, to, false ); -+ } -+ public Int2ObjectSortedMap tailMap( int from ) { -+ return new Submap( from, false, (0), true ); -+ } -+ public Int2ObjectSortedMap subMap( int from, int to ) { -+ return new Submap( from, false, to, false ); -+ } -+ /** A submap with given range. -+ * -+ *

This class represents a submap. One has to specify the left/right -+ * limits (which can be set to -∞ or ∞). 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 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 -∞. */ -+ boolean bottom; -+ /** If true, the submap range goes to ∞. */ -+ boolean top; -+ /** Cached set of entries. */ -+ @SuppressWarnings("hiding") -+ protected transient ObjectSortedSet > entries; -+ /** Cached set of keys. */ -+ @SuppressWarnings("hiding") -+ protected transient IntSortedSet keys; -+ /** Cached collection of values. */ -+ @SuppressWarnings("hiding") -+ protected transient ObjectCollection 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 -∞. -+ * @param to the end of the submap range. -+ * @param top if true, the third parameter is ignored and the range goes to ∞. -+ */ -+ 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 > int2ObjectEntrySet() { -+ if ( entries == null ) entries = new AbstractObjectSortedSet >() { -+ public ObjectBidirectionalIterator > iterator() { -+ return new SubmapEntryIterator(); -+ } -+ public ObjectBidirectionalIterator > iterator( final Int2ObjectMap.Entry from ) { -+ return new SubmapEntryIterator( from.getIntKey() ); -+ } -+ public Comparator > comparator() { return Int2ObjectRBTreeMap.this.int2ObjectEntrySet().comparator(); } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if (!(o instanceof Map.Entry)) return false; -+ final Map.Entry e = (Map.Entry)o; -+ final Int2ObjectRBTreeMap.Entry 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 e = (Map.Entry)o; -+ final Int2ObjectRBTreeMap.Entry 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 first() { return firstEntry(); } -+ public Int2ObjectMap.Entry last() { return lastEntry(); } -+ public ObjectSortedSet > subSet( Int2ObjectMap.Entry from, Int2ObjectMap.Entry to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > headSet( Int2ObjectMap.Entry to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); } -+ public ObjectSortedSet > tailSet( Int2ObjectMap.Entry from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); } -+ }; -+ return entries; -+ } -+ private class KeySet extends AbstractInt2ObjectSortedMap .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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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 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 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 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 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 null if the submap is empty. -+ */ -+ public Int2ObjectRBTreeMap.Entry 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 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 null if the submap is empty. -+ */ -+ public Int2ObjectRBTreeMap.Entry 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 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 e = firstEntry(); -+ if ( e == null ) throw new NoSuchElementException(); -+ return e.key; -+ } -+ public int lastIntKey() { -+ Int2ObjectRBTreeMap.Entry 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 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 e = lastEntry(); -+ if ( e == null ) throw new NoSuchElementException(); -+ return e.getKey(); -+ } -+ /** An iterator for subranges. -+ * -+ *

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 null. -+ */ -+ 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 > { -+ SubmapEntryIterator() {} -+ SubmapEntryIterator( final int k ) { -+ super( k ); -+ } -+ public Int2ObjectMap.Entry next() { return nextEntry(); } -+ public Int2ObjectMap.Entry previous() { return previousEntry(); } -+ public void set( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ public void add( Int2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ /** An iterator on a subrange of keys. -+ * -+ *

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. -+ * -+ *

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 { -+ 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. -+ * -+ *

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 clone() { -+ Int2ObjectRBTreeMap c; -+ try { -+ c = (Int2ObjectRBTreeMap )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 e, p, q, rp = new Entry (), rq = new Entry (); -+ 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 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 readTree( final java.io.ObjectInputStream s, final int n, final Entry pred, final Entry succ ) throws java.io.IOException, ClassNotFoundException { -+ if ( n == 1 ) { -+ final Entry top = new Entry ( 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 top = new Entry ( s.readInt(), (V) s.readObject() ); -+ top.black( true ); -+ top.right( new Entry ( 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 top = new Entry (); -+ 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 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 int checkTree( Entry 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends Int2ObjectMap , SortedMap { -+ /** A sorted entry set providing fast iteration. -+ * -+ *

In some cases (e.g., hash-based classes) iteration over an entry set requires the creation -+ * of a large number of entry objects. Some fastutil -+ * maps might return {@linkplain #entrySet() entry set} objects of type FastSortedEntrySet: in this case, {@link #fastIterator() fastIterator()} -+ * will return an iterator that is guaranteed not to create a large number of objects, possibly -+ * by returning always the same entry (of course, mutated). -+ */ -+ public interface FastSortedEntrySet extends ObjectSortedSet >, FastEntrySet { -+ /** 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 > fastIterator( Int2ObjectMap.Entry 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> 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 > 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. -+ *

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 values(); -+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering. -+ * -+ *

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 fromKey, inclusive, to toKey, exclusive. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}. -+ * -+ * @see SortedMap#subMap(Object,Object) -+ */ -+ Int2ObjectSortedMap subMap(Integer fromKey, Integer toKey); -+ /** Returns a view of the portion of this sorted map whose keys are strictly less than toKey. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}. -+ * -+ * @see SortedMap#headMap(Object) -+ */ -+ Int2ObjectSortedMap headMap(Integer toKey); -+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to fromKey. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}. -+ * -+ * @see SortedMap#tailMap(Object) -+ */ -+ Int2ObjectSortedMap tailMap(Integer fromKey); -+ /** Returns a view of the portion of this sorted map whose keys range from fromKey, inclusive, to toKey, exclusive. -+ * @see SortedMap#subMap(Object,Object) -+ */ -+ Int2ObjectSortedMap subMap(int fromKey, int toKey); -+ /** Returns a view of the portion of this sorted map whose keys are strictly less than toKey. -+ * @see SortedMap#headMap(Object) -+ */ -+ Int2ObjectSortedMap headMap(int toKey); -+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to fromKey. -+ * @see SortedMap#tailMap(Object) -+ */ -+ Int2ObjectSortedMap 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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> entryComparator( final IntComparator comparator ) { -+ return new Comparator>() { -+ public int compare( Map.Entry x, Map.Entry y ) { -+ return comparator.compare( x.getKey(), y.getKey() ); -+ } -+ }; -+ } -+ /** An immutable class representing an empty type-specific sorted map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted map. -+ */ -+ public static class EmptySortedMap extends Int2ObjectMaps.EmptyMap implements Int2ObjectSortedMap , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected EmptySortedMap() {} -+ public IntComparator comparator() { return null; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet > int2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet> entrySet() { return ObjectSortedSets.EMPTY_SET; } -+ -+ public IntSortedSet keySet() { return IntSortedSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public Int2ObjectSortedMap subMap( final int from, final int to ) { return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Int2ObjectSortedMap headMap( final int to ) { return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Int2ObjectSortedMap 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 headMap( Integer oto ) { return headMap( ((oto).intValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Int2ObjectSortedMap tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Int2ObjectSortedMap 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_MAP}. -+ * @return an empty sorted map (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static Int2ObjectSortedMap emptyMap() { -+ return EMPTY_MAP; -+ } -+ /** An immutable class representing a type-specific singleton sorted map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted map. -+ */ -+ public static class Singleton extends Int2ObjectMaps.Singleton implements Int2ObjectSortedMap , 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 > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Int2ObjectMap.Entry )new SingletonEntry(), (Comparator >)entryComparator( comparator ) ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); } -+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.singleton( key, comparator ); return (IntSortedSet )keys; } -+ @SuppressWarnings("unchecked") -+ public Int2ObjectSortedMap 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 headMap( final int to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Int2ObjectSortedMap 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 headMap( Integer oto ) { return headMap( ((oto).intValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Int2ObjectSortedMap tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Int2ObjectSortedMap 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectSortedMap singleton( final Integer key, V value ) { -+ return new Singleton ( ((key).intValue()), (value) ); -+ } -+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectSortedMap singleton( final Integer key, V value, IntComparator comparator ) { -+ return new Singleton ( ((key).intValue()), (value), comparator ); -+ } -+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectSortedMap singleton( final int key, final V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Int2ObjectSortedMap singleton( final int key, final V value, IntComparator comparator ) { -+ return new Singleton ( key, value, comparator ); -+ } -+ /** A synchronized wrapper class for sorted maps. */ -+ public static class SynchronizedSortedMap extends Int2ObjectMaps.SynchronizedMap implements Int2ObjectSortedMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectSortedMap sortedMap; -+ protected SynchronizedSortedMap( final Int2ObjectSortedMap m, final Object sync ) { -+ super( m, sync ); -+ sortedMap = m; -+ } -+ protected SynchronizedSortedMap( final Int2ObjectSortedMap m ) { -+ super( m ); -+ sortedMap = m; -+ } -+ public IntComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } } -+ public ObjectSortedSet > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.int2ObjectEntrySet(), sync ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); } -+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.synchronize( sortedMap.keySet(), sync ); return (IntSortedSet )keys; } -+ public Int2ObjectSortedMap subMap( final int from, final int to ) { return new SynchronizedSortedMap ( sortedMap.subMap( from, to ), sync ); } -+ public Int2ObjectSortedMap headMap( final int to ) { return new SynchronizedSortedMap ( sortedMap.headMap( to ), sync ); } -+ public Int2ObjectSortedMap tailMap( final int from ) { return new SynchronizedSortedMap ( 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 subMap( final Integer from, final Integer to ) { return new SynchronizedSortedMap ( sortedMap.subMap( from, to ), sync ); } -+ public Int2ObjectSortedMap headMap( final Integer to ) { return new SynchronizedSortedMap ( sortedMap.headMap( to ), sync ); } -+ public Int2ObjectSortedMap tailMap( final Integer from ) { return new SynchronizedSortedMap ( 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 Int2ObjectSortedMap synchronize( final Int2ObjectSortedMap m ) { return new SynchronizedSortedMap ( 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 Int2ObjectSortedMap synchronize( final Int2ObjectSortedMap m, final Object sync ) { return new SynchronizedSortedMap ( m, sync ); } -+ /** An unmodifiable wrapper class for sorted maps. */ -+ public static class UnmodifiableSortedMap extends Int2ObjectMaps.UnmodifiableMap implements Int2ObjectSortedMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Int2ObjectSortedMap sortedMap; -+ protected UnmodifiableSortedMap( final Int2ObjectSortedMap m ) { -+ super( m ); -+ sortedMap = m; -+ } -+ public IntComparator comparator() { return sortedMap.comparator(); } -+ public ObjectSortedSet > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.int2ObjectEntrySet() ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); } -+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.unmodifiable( sortedMap.keySet() ); return (IntSortedSet )keys; } -+ public Int2ObjectSortedMap subMap( final int from, final int to ) { return new UnmodifiableSortedMap ( sortedMap.subMap( from, to ) ); } -+ public Int2ObjectSortedMap headMap( final int to ) { return new UnmodifiableSortedMap ( sortedMap.headMap( to ) ); } -+ public Int2ObjectSortedMap tailMap( final int from ) { return new UnmodifiableSortedMap ( 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 subMap( final Integer from, final Integer to ) { return new UnmodifiableSortedMap ( sortedMap.subMap( from, to ) ); } -+ public Int2ObjectSortedMap headMap( final Integer to ) { return new UnmodifiableSortedMap ( sortedMap.headMap( to ) ); } -+ public Int2ObjectSortedMap tailMap( final Integer from ) { return new UnmodifiableSortedMap ( 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 Int2ObjectSortedMap unmodifiable( final Int2ObjectSortedMap m ) { return new UnmodifiableSortedMap ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

This class provides additional methods that implement a deque (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 null (FIFO queues have no comparator). -+ * @return null. -+ */ -+ @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use as reference list a reference array, -+ * which must be provided to each constructor, and represent a priority queue -+ * using a backing array of integer indices—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. -+ * -+ *

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 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 null 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 null 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. -+ * -+ *

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 refArray. -+ * @param size the number of elements to be included in the queue. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

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 refArray. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

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 refArray. -+ * @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. -+ * -+ *

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 refArray. -+ */ -+ 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. -+ * -+ *

Note that for efficiency reasons this method will not throw an exception -+ * when x 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} -+ * -+ *

Note that for efficiency reasons this method will not throw an exception -+ * when index 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 -+ * never 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. -+ * -+ *

This class implements the bulk methods removeElements(), -+ * addElements() and getElements() 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. -+ * -+ *

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 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 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. -+ * -+ *

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. -+ * -+ *

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 -+ * n, this method does nothing. Otherwise, it trims the -+ * array length to the maximum between n and {@link #size()}. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class represent a priority queue using a backing -+ * array—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. -+ * -+ *

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 null 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 null 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. -+ * -+ *

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 null 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. -+ * -+ *

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 null 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. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

It is responsibility of the caller that the elements of a 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 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. -+ * -+ *

It is responsibility of the caller that the first size elements of a are distinct. -+ * -+ * @param a the backing array. -+ * @param size the number of valid elements in a. -+ */ -+ 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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

In particular, the ensureCapacity(), grow(), -+ * trim() and setLength() methods allow to handle -+ * arrays much like array lists. This can be very useful when efficiency (or -+ * syntactic simplicity) reasons make array lists unsuitable. -+ * -+ *

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. -+ * -+ *

Sorting

-+ * -+ *

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 indirect sorting facility, which makes it possible -+ * to sort an array using the values in another array as comparator. -+ * -+ *

All comparison-based algorithm have an implementation based on a type-specific comparator. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

If you cannot foresee whether this array will need again to be -+ * enlarged, you should probably use grow() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it contains length entries or more; otherwise, -+ * an array with length entries whose first array.length -+ * entries are the same as those of array. -+ */ -+ 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 array, if it can contain length entries or more; otherwise, -+ * an array with length entries whose first preserve -+ * entries are the same as those of array. -+ */ -+ 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * array.length entries are the same as those of array. -+ * */ -+ 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() 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 array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * preserve entries are the same as those of array. -+ * */ -+ 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 array, if it contains length -+ * entries or less; otherwise, an array with -+ * length entries whose entries are the same as -+ * the first length entries of array. -+ * -+ */ -+ 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 array, if it contains exactly length -+ * entries; otherwise, if it contains more than -+ * length entries, an array with length entries -+ * whose entries are the same as the first length entries of -+ * array; otherwise, an array with length entries -+ * whose first array.length entries are the same as those of -+ * array. -+ * -+ */ -+ 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 length elements of array starting at offset. -+ */ -+ 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 array. -+ */ -+ 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. -+ * -+ *

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 from is greater than to. -+ * @throws ArrayIndexOutOfBoundsException if from or to 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. -+ * -+ *

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 length is negative. -+ * @throws ArrayIndexOutOfBoundsException if offset is negative or offset+length 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

This sort is guaranteed to be stable: 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 to 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: 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 to 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @param a the array to be sorted. -+ * @param from the index of the first element of perm (inclusive) to be permuted. -+ * @param to the index of the last element of perm (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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation uses a pool of {@link Runtime#availableProcessors()} threads. -+ * -+ * @param perm a permutation array indexing a. -+ * @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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ final int[] support = stable ? new int[ perm.length ] : null; -+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation uses a pool of {@link Runtime#availableProcessors()} threads. -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ *

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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ for ( int i = numberOfThreads; i-- != 0; ) -+ executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a further support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a further support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @param a the array to be sorted. -+ * @param b the second array to be sorted. -+ * @param from the index of the first element of perm (inclusive) to be permuted. -+ * @param to the index of the last element of perm (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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 XorShift* generator). -+ * @return a. -+ */ -+ 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 XorShift* generator). -+ * @return a. -+ */ -+ 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 a. -+ */ -+ 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 a. -+ */ -+ 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, 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. -+ * -+ *

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 null correctly, and it is serializable. -+ */ -+ public final static Hash.Strategy 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * 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. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #previous()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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, IntIterable { -+ /** Returns a type-specific iterator on the elements of this collection. -+ * -+ *

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 fastutil 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. -+ * -+ *

Warning: 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[] 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. -+ * -+ *

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. -+ * -+ *

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 -+ * remove(). -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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[] 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 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 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[] 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Note that fastutil 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 { -+ /** 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 c. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use an additional inversion array, 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. -+ * -+ *

This implementation does not 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 null 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 null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @param size the number of elements to be included in the queue. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

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 a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @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. -+ * -+ *

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 a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null 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 null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a 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 null 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. -+ * -+ *

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 a one by one). -+ * -+ * @param a an array. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a 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. -+ * -+ *

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 a 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. -+ * -+ *

This constructor is more efficient than enqueing the elements of collection 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 null 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. -+ * -+ *

This constructor is -+ * more efficient than enqueing the elements of collection 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. -+ * -+ *

This constructor is more efficient than enqueing the elements of collection 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 null for the natural order. -+ */ -+ public IntHeapPriorityQueue( final Collection collection, final IntComparator c ) { -+ this( collection.size(), c ); -+ final Iterator 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. -+ * -+ *

This constructor is -+ * more efficient than enqueing the elements of collection one by one. -+ * -+ * @param collection a collection; its elements will be used to initialize the queue. -+ */ -+ public IntHeapPriorityQueue( final Collection 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use as reference list a reference array, -+ * 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. -+ * -+ *

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 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 null 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 null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @param size the number of elements to be included in the queue. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

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 a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @param c the comparator used in this queue, or null 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. -+ * -+ *

The queue returned by this method will be backed by the given array. -+ * The first size element of the array will be rearranged so to form a heap (this is -+ * more efficient than enqueing the elements of a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ * @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. -+ * -+ *

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 a one by one). -+ * -+ * @param refArray the reference array. -+ * @param a an array of indices into refArray. -+ */ -+ 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} -+ * -+ *

The caller must 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null for the natural order. -+ * @return the new position of the element of index i. -+ */ -+ -+ 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 null for the natural order. -+ * @return the new position of the element of index i. -+ */ -+ -+ 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 null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

An indirect heap is an extension of a semi-indirect heap using also an -+ * inversion array of the same length as the reference array, -+ * satisfying the relation heap[inv[i]]==i when -+ * inv[i]>=0, and inv[heap[i]]==i 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 null for the natural order. -+ * @return the new position in the heap of the element of heap index i. -+ */ -+ -+ 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 null for the natural order. -+ * @return the new position in the heap of the element of heap index i. -+ */ -+ -+ 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 null 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 refArray. -+ * @param inv the inversion array. -+ * @param size the number of elements in the heap. -+ * @param c a type-specific comparator, or null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

Additionally, this interface strengthens {@link #comparator()}. -+ */ -+public interface IntIndirectPriorityQueue extends IndirectPriorityQueue { -+ /** 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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()}. -+ * -+ *

Warning: Java will let you write “colon” for statements with primitive-type -+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an -+ * unboxing (and, in the case of fastutil type-specific data structures, a boxing) will be performed. Watch out. -+ * -+ * @see Iterable -+ */ -+public interface IntIterable extends Iterable { -+ /** 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * 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. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #next()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 element. -+ */ -+ 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. -+ * -+ *

The type-specific list iterator returned by this method will iterate -+ * length times, returning consecutive elements of the given -+ * array starting from the one with index offset. -+ * -+ * @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 length elements of array starting at position offset. -+ */ -+ 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. -+ * -+ *

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 array. -+ */ -+ 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. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of length, in the given array starting at offset. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and returns an array -+ * containing the elements returned by the iterator. At most max 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 max). -+ */ -+ -+ 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of max, in the given type-specific collection. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and adds -+ * the returned elements to the given collection (up to max). -+ * -+ * @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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and returns -+ * a type-specific list containing the returned elements (up to max). 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 max. -+ */ -+ 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. -+ * -+ *

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 i; -+ public IteratorWrapper( final Iterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ @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 i; -+ public ListIteratorWrapper( final ListIterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ @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. -+ * -+ *

The type-specific list iterator returned by this method will return the -+ * elements from, from+1,…, to-1. -+ * -+ * @param from the starting element (inclusive). -+ * @param to the ending element (exclusive). -+ * @return a type-specific list iterator enumerating the elements from from to to. -+ */ -+ 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. -+ * -+ *

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. -+ * -+ *

This method returns an iterator that will enumerate in order the elements returned -+ * by a[ offset ], then those returned -+ * by a[ offset + 1 ], and so on up to -+ * a[ offset + length - 1 ]. -+ * -+ * @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 length elements of a starting at offset. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a set. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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. -+ * -+ *

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 -+ * via an array of longs parallel to the table. -+ * -+ *

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 null. -+ * -+ *

Additional methods, such as addAndMoveToFirst(), make it easy -+ * to use instances of this class as a cache (e.g., with LRU policy). -+ * -+ *

The iterators provided by this class are type-specific {@linkplain -+ * java.util.ListIterator list iterators}, and can be started at any -+ * element which is in the set (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 ((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL). -+ * 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. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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. -+ * -+ *

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 fastutil 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 fastutil 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. -+ * -+ *

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 null 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 null 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 from 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this set in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a set. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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. -+ * -+ *

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 -+ * via an array of longs parallel to the table. -+ * -+ *

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 null. -+ * -+ *

Additional methods, such as addAndMoveToFirst(), make it easy -+ * to use instances of this class as a cache (e.g., with LRU policy). -+ * -+ *

The iterators provided by this class are type-specific {@linkplain -+ * java.util.ListIterator list iterators}, and can be started at any -+ * element which is in the set (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 ((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL). -+ * 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. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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. -+ * -+ *

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 fastutil 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 fastutil 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. -+ * -+ *

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 null 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 null 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 from 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this set in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

Additionally, this interface strengthens {@link #listIterator()}, -+ * {@link #listIterator(int)} and {@link #subList(int,int)}. -+ * -+ *

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, Comparable>, 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 fastutil 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 fastutil 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 from, inclusive, to the index to, exclusive. -+ * @see List#subList(int,int) -+ * @deprecated As of fastutil 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 from, inclusive, to the index to, exclusive. -+ * -+ *

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. -+ * -+ *

If the specified size is smaller than the current size, the last elements are -+ * discarded. Otherwise, they are filled with 0/null/false. -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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, 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 XorShift* generator). -+ * @return l. -+ */ -+ 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. -+ * -+ *

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 c ) { throw new UnsupportedOperationException(); } -+ public boolean addAll( int i, Collection 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 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. -+ * -+ *

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 c ) { throw new UnsupportedOperationException(); } -+ public boolean addAll( final int i, final Collection 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 element. -+ */ -+ 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 element. -+ */ -+ 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 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 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 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this interface strengthens {@link #comparator()}. -+ */ -+public interface IntPriorityQueue extends PriorityQueue { -+ /** 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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

A semi-indirect heap is based on a reference array. Elements of -+ * a semi-indirect heap are integers that index the reference array (note that -+ * in an indirect 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 null for the natural order. -+ * @return the new position in the heap of the element of heap index i. -+ */ -+ -+ 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 null for the natural order. -+ * @return the new position in the heap of the element of heap index i. -+ */ -+ -+ 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 null 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 null 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 refArray. -+ * @param size the number of elements in the heap. -+ * @param c a type-specific comparator, or null 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. -+ * -+ *

The front 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. -+ * -+ *

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 refArray. -+ * @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 refArray). -+ * @return the number of elements actually written (starting from the first position of a). -+ */ -+ -+ 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. -+ * -+ *

The front 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. -+ * -+ *

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 refArray. -+ * @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 refArray). -+ * @param c a type-specific comparator. -+ * @return the number of elements actually written (starting from the first position of a). -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this interface strengthens (again) {@link #iterator()}. -+ * -+ * @see Set -+ */ -+public interface IntSet extends IntCollection , Set { -+ /** Returns a type-specific iterator on the elements of this set. -+ * -+ *

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. -+ * -+ *

Note that the corresponding method of the type-specific collection is rem(). -+ * 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 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 element. -+ */ -+ 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 element. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 { -+ /** 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). -+ * -+ *

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 -+ * false). 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 false). -+ * -+ *

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. -+ * -+ *

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 fastutil 5, replaced by {@link #iterator()}. -+ */ -+ @Deprecated -+ IntBidirectionalIterator intIterator(); -+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in -+ * this set. -+ * -+ *

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 fromElement, inclusive, to toElement, exclusive. -+ * -+ *

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 toElement. -+ * -+ *

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 fromElement. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 element. -+ */ -+ 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 element. -+ */ -+ 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 element. -+ */ -+ 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 element. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * @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 @@ -+ -+ -+ -+ fastutil -+ -+ -+ -+ -+

Provides type-specific classes for integer elements or keys. -+ -+ -+ -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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null on a missing key). -+ * -+ *

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 -+ * defRetValue to denote lack of a key in type-specific methods. The value -+ * is serialized. -+ * -+ *

Implementing subclasses have just to provide type-specific get(), -+ * type-specific containsKey(), and size() methods. -+ * -+ */ -+public abstract class AbstractLong2ObjectFunction implements Long2ObjectFunction , java.io.Serializable { -+ private static final long serialVersionUID = -4940583368468432370L; -+ protected AbstractLong2ObjectFunction() {} -+ /** -+ * The default return value for get(), put() and -+ * remove(). -+ */ -+ 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 null on a missing key. -+ * -+ *

This method must check whether the provided key is in the map using containsKey(). Thus, -+ * it probes the map twice. 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null on a missing key). -+ * -+ *

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 extends AbstractLong2ObjectFunction implements Long2ObjectMap , 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 m) { -+ int n = m.size(); -+ final Iterator> i = m.entrySet().iterator(); -+ if (m instanceof Long2ObjectMap) { -+ Long2ObjectMap.Entry e; -+ while(n-- != 0) { -+ e = (Long2ObjectMap.Entry )i.next(); -+ put(e.getLongKey(), e.getValue()); -+ } -+ } -+ else { -+ Map.Entry 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). -+ * -+ *

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 implements Long2ObjectMap.Entry { -+ 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. -+ * -+ *

The view is backed by the set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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> i = entrySet().iterator(); -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public long nextLong() { return ((Long2ObjectMap.Entry )i.next()).getLongKey(); }; -+ public boolean hasNext() { return i.hasNext(); } -+ }; -+ } -+ }; -+ } -+ /** Returns a type-specific-set view of the values of this map. -+ * -+ *

The view is backed by the set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 values() { -+ return new AbstractObjectCollection () { -+ public boolean contains( final Object k ) { return containsValue( k ); } -+ public int size() { return AbstractLong2ObjectMap.this.size(); } -+ public void clear() { AbstractLong2ObjectMap.this.clear(); } -+ public ObjectIterator iterator() { -+ return new AbstractObjectIterator () { -+ final ObjectIterator> i = entrySet().iterator(); -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public V next() { return ((Long2ObjectMap.Entry )i.next()).getValue(); }; -+ public boolean hasNext() { return i.hasNext(); } -+ }; -+ } -+ }; -+ } -+ @SuppressWarnings({ "unchecked", "rawtypes" }) -+ public ObjectSet> 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> 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> i = entrySet().iterator(); -+ int n = size(); -+ Long2ObjectMap.Entry e; -+ boolean first = true; -+ s.append("{"); -+ while(n-- != 0) { -+ if (first) first = false; -+ else s.append(", "); -+ e = (Long2ObjectMap.Entry )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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends AbstractLong2ObjectMap implements Long2ObjectSortedMap { -+ 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 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 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 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. -+ * -+ *

The view is backed by the sorted set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 ( entrySet().iterator( new BasicEntry ( from, (null) ) ) ); } -+ public LongBidirectionalIterator iterator() { return new KeySetIterator ( entrySet().iterator() ); } -+ } -+ /** A wrapper exhibiting a map iterator as an iterator on keys. -+ * -+ *

To provide an iterator on keys, just create an instance of this -+ * class using the corresponding iterator on entries. -+ */ -+ protected static class KeySetIterator extends AbstractLongBidirectionalIterator { -+ protected final ObjectBidirectionalIterator> i; -+ public KeySetIterator( ObjectBidirectionalIterator> 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. -+ * -+ *

The view is backed by the sorted set returned by {@link #entrySet()}. Note that -+ * no attempt is made at caching the result of this method, 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 values() { -+ return new ValuesCollection(); -+ } -+ /** A wrapper exhibiting the values of a map. */ -+ protected class ValuesCollection extends AbstractObjectCollection { -+ public ObjectIterator iterator() { return new ValuesIterator ( 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. -+ * -+ *

To provide an iterator on values, just create an instance of this -+ * class using the corresponding iterator on entries. -+ */ -+ protected static class ValuesIterator extends AbstractObjectIterator { -+ protected final ObjectBidirectionalIterator> i; -+ public ValuesIterator( ObjectBidirectionalIterator> i ) { -+ this.i = i; -+ } -+ public V next() { return (i.next().getValue()); }; -+ public boolean hasNext() { return i.hasNext(); } -+ } -+ @SuppressWarnings({ "unchecked", "rawtypes" }) -+ public ObjectSortedSet> 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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). -+ * -+ *

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 n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

In particular, this class provide {@link #iterator()}, add(), {@link #remove(Object)} and -+ * {@link #contains(Object)} methods that just call the type-specific counterpart. -+ */ -+public abstract class AbstractLongCollection extends AbstractCollection 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 true 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 true 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 true 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 true 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[] 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 true if this collection changed as a result of the call. -+ */ -+ public boolean addAll( Collection c ) { -+ boolean retVal = false; -+ final Iterator 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 rem() 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 true 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 true 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 true 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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). -+ * -+ *

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 -+ * n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 c ) { -+ ensureIndex( index ); -+ int n = c.size(); -+ if ( n == 0 ) return false; -+ Iterator i = c.iterator(); -+ while( n-- != 0 ) add( index++, i.next() ); -+ return true; -+ } -+ /** Delegates to a more generic method. */ -+ public boolean addAll( final Collection 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 ClassCastException. -+ * -+ * @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 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 i1 = listIterator(), i2 = l.listIterator(); -+ int r; -+ while( i1.hasNext() && i2.hasNext() ) { -+ if ( ( r = ((Comparable)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 rem(). */ -+ 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)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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 remove(). -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends AbstractLong2ObjectMap 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. -+ * -+ *

It is responsibility of the caller that the elements of key are distinct. -+ * -+ * @param key the key array. -+ * @param value the value array (it must have the same length as key). -+ */ -+ 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 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 m ) { -+ this( m.size() ); -+ putAll( m ); -+ } -+ /** Creates a new array map with given key and value backing arrays, using the given number of elements. -+ * -+ *

It is responsibility of the caller that the first size elements of key are distinct. -+ * -+ * @param key the key array. -+ * @param value the value array (it must have the same length as key). -+ * @param size the number of valid elements in key and value. -+ */ -+ 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 > implements FastEntrySet { -+ @Override -+ public ObjectIterator > iterator() { -+ return new AbstractObjectIterator >() { -+ int curr = -1, next = 0; -+ public boolean hasNext() { -+ return next < size; -+ } -+ @SuppressWarnings("unchecked") -+ public Entry next() { -+ if ( ! hasNext() ) throw new NoSuchElementException(); -+ return new AbstractLong2ObjectMap.BasicEntry ( 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 > fastIterator() { -+ return new AbstractObjectIterator >() { -+ int next = 0, curr = -1; -+ final BasicEntry entry = new BasicEntry ( (0), (null) ); -+ public boolean hasNext() { -+ return next < size; -+ } -+ @SuppressWarnings("unchecked") -+ public Entry 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 e = (Map.Entry)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 e = (Map.Entry)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 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 values() { -+ return ObjectCollections.unmodifiable( new ObjectArraySet ( value, size ) ); -+ } -+ /** Returns a deep copy of this map. -+ * -+ *

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 clone() { -+ Long2ObjectArrayMap c; -+ try { -+ c = (Long2ObjectArrayMap )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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Type-specific versions of get(), put() and -+ * remove() cannot rely on null 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 (false -+ * for booleans) at creation, but can be changed using the -+ * defaultReturnValue() method. -+ * -+ *

For uniformity reasons, even maps returning objects implement the default -+ * return value (of course, in this case the default return value is -+ * initialized to null). -+ * -+ *

Warning: 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 get(), put() and -+ * remove() for maps with primitive-type values return -+ * null to denote missing keys 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 extends Function { -+ /** 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 -+ * get(), put() and remove() to -+ * denote that the map does not contain the specified key. It must be -+ * 0/false/null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific function. -+ */ -+ public static class EmptyFunction extends AbstractLong2ObjectFunction 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific function. -+ */ -+ public static class Singleton extends AbstractLong2ObjectFunction 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectFunction singleton( final long key, V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectFunction singleton( final Long key, final V value ) { -+ return new Singleton ( ((key).longValue()), (value) ); -+ } -+ /** A synchronized wrapper class for functions. */ -+ public static class SynchronizedFunction extends AbstractLong2ObjectFunction implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectFunction function; -+ protected final Object sync; -+ protected SynchronizedFunction( final Long2ObjectFunction f, final Object sync ) { -+ if ( f == null ) throw new NullPointerException(); -+ this.function = f; -+ this.sync = sync; -+ } -+ protected SynchronizedFunction( final Long2ObjectFunction 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 Long2ObjectFunction synchronize( final Long2ObjectFunction f ) { return new SynchronizedFunction ( 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 Long2ObjectFunction synchronize( final Long2ObjectFunction f, final Object sync ) { return new SynchronizedFunction ( f, sync ); } -+ /** An unmodifiable wrapper class for functions. */ -+ public static class UnmodifiableFunction extends AbstractLong2ObjectFunction implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectFunction function; -+ protected UnmodifiableFunction( final Long2ObjectFunction 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 Long2ObjectFunction unmodifiable( final Long2ObjectFunction f ) { return new UnmodifiableFunction ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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. -+ * -+ *

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 -+ * via an array of longs parallel to the table. -+ * -+ *

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 null. -+ * -+ *

Additional methods, such as getAndMoveToFirst(), make it easy -+ * to use instances of this class as a cache (e.g., with LRU policy). -+ * -+ *

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 which is a key of the map, 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 extends AbstractLong2ObjectSortedMap 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 ((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL). -+ * 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 entries; -+ /** Cached set of keys. */ -+ protected transient LongSortedSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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. -+ *

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 tailMap( long from ) { throw new UnsupportedOperationException(); } -+ public Long2ObjectSortedMap headMap( long to ) { throw new UnsupportedOperationException(); } -+ public Long2ObjectSortedMap subMap( long from, long to ) { throw new UnsupportedOperationException(); } -+ /** A list iterator over a linked map. -+ * -+ *

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 null 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 null 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 > { -+ 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 ok ) { throw new UnsupportedOperationException(); } -+ public void add( Long2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ private class FastEntryIterator extends MapIterator implements ObjectListIterator > { -+ 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 ok ) { throw new UnsupportedOperationException(); } -+ public void add( Long2ObjectMap.Entry ok ) { throw new UnsupportedOperationException(); } -+ } -+ private final class MapEntrySet extends AbstractObjectSortedSet > implements FastSortedEntrySet { -+ public ObjectBidirectionalIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public Comparator > comparator() { return null; } -+ public ObjectSortedSet > subSet( Long2ObjectMap.Entry fromElement, Long2ObjectMap.Entry toElement) { throw new UnsupportedOperationException(); } -+ public ObjectSortedSet > headSet( Long2ObjectMap.Entry toElement ) { throw new UnsupportedOperationException(); } -+ public ObjectSortedSet > tailSet( Long2ObjectMap.Entry fromElement ) { throw new UnsupportedOperationException(); } -+ public Long2ObjectMap.Entry first() { -+ if ( size == 0 ) throw new NoSuchElementException(); -+ return new MapEntry( Long2ObjectLinkedOpenHashMap.this.first ); -+ } -+ public Long2ObjectMap.Entry 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 e = (Map.Entry)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 e = (Map.Entry)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 > iterator( final Long2ObjectMap.Entry from ) { -+ return new EntryIterator( from.getLongKey() ); -+ } -+ public ObjectBidirectionalIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ public ObjectBidirectionalIterator > fastIterator( final Long2ObjectMap.Entry from ) { -+ return new FastEntryIterator( from.getLongKey() ); -+ } -+ } -+ public FastSortedEntrySet long2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ 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 values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Long2ObjectLinkedOpenHashMap c; -+ try { -+ c = (Long2ObjectLinkedOpenHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 extends Long2ObjectFunction , Map { -+ /** An entry set providing fast iteration. -+ * -+ *

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 fastutil -+ * maps might return {@linkplain #entrySet() entry set} objects of type FastEntrySet: in this case, {@link #fastIterator() fastIterator()} -+ * will return an iterator that is guaranteed not to create a large number of objects, possibly -+ * by returning always the same entry (of course, mutated). -+ */ -+ public interface FastEntrySet extends ObjectSet > { -+ /** 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 > fastIterator(); -+ } -+ /** Returns a set view of the mappings contained in this map. -+ *

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> entrySet(); -+ /** Returns a type-specific set view of the mappings contained in this map. -+ * -+ *

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 > long2ObjectEntrySet(); -+ /** Returns a set view of the keys contained in this map. -+ *

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. -+ *

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 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 extends Map.Entry { -+ /** {@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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific map. -+ */ -+ public static class EmptyMap extends Long2ObjectFunctions.EmptyFunction implements Long2ObjectMap , 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 m ) { throw new UnsupportedOperationException(); } -+ @SuppressWarnings("unchecked") -+ public ObjectSet > long2ObjectEntrySet() { return ObjectSets.EMPTY_SET; } -+ -+ public LongSet keySet() { return LongSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectCollection 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> 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_MAP}. -+ * @return an empty map (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static Long2ObjectMap emptyMap() { -+ return EMPTY_MAP; -+ } -+ /** An immutable class representing a type-specific singleton map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific map. -+ */ -+ public static class Singleton extends Long2ObjectFunctions.Singleton implements Long2ObjectMap , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected transient ObjectSet > entries; -+ protected transient LongSet keys; -+ protected transient ObjectCollection 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 m ) { throw new UnsupportedOperationException(); } -+ public ObjectSet > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Long2ObjectMap.Entry )new SingletonEntry() ); return entries; } -+ public LongSet keySet() { if ( keys == null ) keys = LongSets.singleton( key ); return keys; } -+ public ObjectCollection values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; } -+ protected class SingletonEntry implements Long2ObjectMap.Entry , Map.Entry { -+ /** {@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> 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectMap singleton( final long key, V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectMap singleton( final Long key, final V value ) { -+ return new Singleton ( ((key).longValue()), (value) ); -+ } -+ /** A synchronized wrapper class for maps. */ -+ public static class SynchronizedMap extends Long2ObjectFunctions.SynchronizedFunction implements Long2ObjectMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectMap map; -+ protected transient ObjectSet > entries; -+ protected transient LongSet keys; -+ protected transient ObjectCollection values; -+ protected SynchronizedMap( final Long2ObjectMap m, final Object sync ) { -+ super( m, sync ); -+ this.map = m; -+ } -+ protected SynchronizedMap( final Long2ObjectMap 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 m ) { synchronized( sync ) { map.putAll( m ); } } -+ public ObjectSet > 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 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> 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 Long2ObjectMap synchronize( final Long2ObjectMap m ) { return new SynchronizedMap ( 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 Long2ObjectMap synchronize( final Long2ObjectMap m, final Object sync ) { return new SynchronizedMap ( m, sync ); } -+ /** An unmodifiable wrapper class for maps. */ -+ public static class UnmodifiableMap extends Long2ObjectFunctions.UnmodifiableFunction implements Long2ObjectMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectMap map; -+ protected transient ObjectSet > entries; -+ protected transient LongSet keys; -+ protected transient ObjectCollection values; -+ protected UnmodifiableMap( final Long2ObjectMap 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 m ) { throw new UnsupportedOperationException(); } -+ public ObjectSet > 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 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> 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 Long2ObjectMap unmodifiable( final Long2ObjectMap m ) { return new UnmodifiableMap ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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 extends AbstractLong2ObjectMap 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 entries; -+ /** Cached set of keys. */ -+ protected transient LongSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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 > { -+ private MapEntry entry; -+ public Long2ObjectMap.Entry 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 > { -+ private final MapEntry entry = new MapEntry(); -+ public MapEntry next() { -+ entry.index = nextEntry(); -+ return entry; -+ } -+ } -+ private final class MapEntrySet extends AbstractObjectSet > implements FastEntrySet { -+ public ObjectIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if ( !( o instanceof Map.Entry ) ) return false; -+ final Map.Entry e = (Map.Entry)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 e = (Map.Entry)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 long2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ public ValueIterator() { super(); } -+ public V next() { return value[ nextEntry() ]; } -+ } -+ public ObjectCollection values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Long2ObjectOpenCustomHashMap c; -+ try { -+ c = (Long2ObjectOpenCustomHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a map. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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 extends AbstractLong2ObjectMap 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 entries; -+ /** Cached set of keys. */ -+ protected transient LongSet keys; -+ /** Cached collection of values. */ -+ protected transient ObjectCollection values; -+ /** Creates a new hash map. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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 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 k and v 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 k and v 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 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. -+ * -+ *

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 fastutil 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 fastutil 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 , Map.Entry { -+ // 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 e = (Map.Entry)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 > { -+ private MapEntry entry; -+ public Long2ObjectMap.Entry 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 > { -+ private final MapEntry entry = new MapEntry(); -+ public MapEntry next() { -+ entry.index = nextEntry(); -+ return entry; -+ } -+ } -+ private final class MapEntrySet extends AbstractObjectSet > implements FastEntrySet { -+ public ObjectIterator > iterator() { -+ return new EntryIterator(); -+ } -+ public ObjectIterator > fastIterator() { -+ return new FastEntryIterator(); -+ } -+ @SuppressWarnings("unchecked") -+ public boolean contains( final Object o ) { -+ if ( !( o instanceof Map.Entry ) ) return false; -+ final Map.Entry e = (Map.Entry)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 e = (Map.Entry)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 long2ObjectEntrySet() { -+ if ( entries == null ) entries = new MapEntrySet(); -+ return entries; -+ } -+ /** An iterator on keys. -+ * -+ *

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. -+ * -+ *

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 { -+ public ValueIterator() { super(); } -+ public V next() { return value[ nextEntry() ]; } -+ } -+ public ObjectCollection values() { -+ if ( values == null ) values = new AbstractObjectCollection () { -+ public ObjectIterator 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this map in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 clone() { -+ Long2ObjectOpenHashMap c; -+ try { -+ c = (Long2ObjectOpenHashMap )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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends Long2ObjectMap , SortedMap { -+ /** A sorted entry set providing fast iteration. -+ * -+ *

In some cases (e.g., hash-based classes) iteration over an entry set requires the creation -+ * of a large number of entry objects. Some fastutil -+ * maps might return {@linkplain #entrySet() entry set} objects of type FastSortedEntrySet: in this case, {@link #fastIterator() fastIterator()} -+ * will return an iterator that is guaranteed not to create a large number of objects, possibly -+ * by returning always the same entry (of course, mutated). -+ */ -+ public interface FastSortedEntrySet extends ObjectSortedSet >, FastEntrySet { -+ /** 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 > fastIterator( Long2ObjectMap.Entry 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> 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 > 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. -+ *

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 values(); -+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering. -+ * -+ *

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 fromKey, inclusive, to toKey, exclusive. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}. -+ * -+ * @see SortedMap#subMap(Object,Object) -+ */ -+ Long2ObjectSortedMap subMap(Long fromKey, Long toKey); -+ /** Returns a view of the portion of this sorted map whose keys are strictly less than toKey. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}. -+ * -+ * @see SortedMap#headMap(Object) -+ */ -+ Long2ObjectSortedMap headMap(Long toKey); -+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to fromKey. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}. -+ * -+ * @see SortedMap#tailMap(Object) -+ */ -+ Long2ObjectSortedMap tailMap(Long fromKey); -+ /** Returns a view of the portion of this sorted map whose keys range from fromKey, inclusive, to toKey, exclusive. -+ * @see SortedMap#subMap(Object,Object) -+ */ -+ Long2ObjectSortedMap subMap(long fromKey, long toKey); -+ /** Returns a view of the portion of this sorted map whose keys are strictly less than toKey. -+ * @see SortedMap#headMap(Object) -+ */ -+ Long2ObjectSortedMap headMap(long toKey); -+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to fromKey. -+ * @see SortedMap#tailMap(Object) -+ */ -+ Long2ObjectSortedMap 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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> entryComparator( final LongComparator comparator ) { -+ return new Comparator>() { -+ public int compare( Map.Entry x, Map.Entry y ) { -+ return comparator.compare( x.getKey(), y.getKey() ); -+ } -+ }; -+ } -+ /** An immutable class representing an empty type-specific sorted map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted map. -+ */ -+ public static class EmptySortedMap extends Long2ObjectMaps.EmptyMap implements Long2ObjectSortedMap , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected EmptySortedMap() {} -+ public LongComparator comparator() { return null; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet > long2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet> entrySet() { return ObjectSortedSets.EMPTY_SET; } -+ -+ public LongSortedSet keySet() { return LongSortedSets.EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public Long2ObjectSortedMap subMap( final long from, final long to ) { return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Long2ObjectSortedMap headMap( final long to ) { return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Long2ObjectSortedMap 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 headMap( Long oto ) { return headMap( ((oto).longValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Long2ObjectSortedMap tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Long2ObjectSortedMap 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_MAP}. -+ * @return an empty sorted map (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static Long2ObjectSortedMap emptyMap() { -+ return EMPTY_MAP; -+ } -+ /** An immutable class representing a type-specific singleton sorted map. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted map. -+ */ -+ public static class Singleton extends Long2ObjectMaps.Singleton implements Long2ObjectSortedMap , 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 > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Long2ObjectMap.Entry )new SingletonEntry(), (Comparator >)entryComparator( comparator ) ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); } -+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.singleton( key, comparator ); return (LongSortedSet )keys; } -+ @SuppressWarnings("unchecked") -+ public Long2ObjectSortedMap 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 headMap( final long to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; } -+ @SuppressWarnings("unchecked") -+ public Long2ObjectSortedMap 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 headMap( Long oto ) { return headMap( ((oto).longValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Long2ObjectSortedMap tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); } -+ /** {@inheritDoc} -+ * @deprecated Please use the corresponding type-specific method instead. */ -+ @Deprecated -+ public Long2ObjectSortedMap 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. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectSortedMap singleton( final Long key, V value ) { -+ return new Singleton ( ((key).longValue()), (value) ); -+ } -+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectSortedMap singleton( final Long key, V value, LongComparator comparator ) { -+ return new Singleton ( ((key).longValue()), (value), comparator ); -+ } -+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectSortedMap singleton( final long key, final V value ) { -+ return new Singleton ( key, value ); -+ } -+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable. -+ * -+ *

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 <key,value>. -+ */ -+ public static Long2ObjectSortedMap singleton( final long key, final V value, LongComparator comparator ) { -+ return new Singleton ( key, value, comparator ); -+ } -+ /** A synchronized wrapper class for sorted maps. */ -+ public static class SynchronizedSortedMap extends Long2ObjectMaps.SynchronizedMap implements Long2ObjectSortedMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectSortedMap sortedMap; -+ protected SynchronizedSortedMap( final Long2ObjectSortedMap m, final Object sync ) { -+ super( m, sync ); -+ sortedMap = m; -+ } -+ protected SynchronizedSortedMap( final Long2ObjectSortedMap m ) { -+ super( m ); -+ sortedMap = m; -+ } -+ public LongComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } } -+ public ObjectSortedSet > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.long2ObjectEntrySet(), sync ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); } -+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.synchronize( sortedMap.keySet(), sync ); return (LongSortedSet )keys; } -+ public Long2ObjectSortedMap subMap( final long from, final long to ) { return new SynchronizedSortedMap ( sortedMap.subMap( from, to ), sync ); } -+ public Long2ObjectSortedMap headMap( final long to ) { return new SynchronizedSortedMap ( sortedMap.headMap( to ), sync ); } -+ public Long2ObjectSortedMap tailMap( final long from ) { return new SynchronizedSortedMap ( 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 subMap( final Long from, final Long to ) { return new SynchronizedSortedMap ( sortedMap.subMap( from, to ), sync ); } -+ public Long2ObjectSortedMap headMap( final Long to ) { return new SynchronizedSortedMap ( sortedMap.headMap( to ), sync ); } -+ public Long2ObjectSortedMap tailMap( final Long from ) { return new SynchronizedSortedMap ( 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 Long2ObjectSortedMap synchronize( final Long2ObjectSortedMap m ) { return new SynchronizedSortedMap ( 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 Long2ObjectSortedMap synchronize( final Long2ObjectSortedMap m, final Object sync ) { return new SynchronizedSortedMap ( m, sync ); } -+ /** An unmodifiable wrapper class for sorted maps. */ -+ public static class UnmodifiableSortedMap extends Long2ObjectMaps.UnmodifiableMap implements Long2ObjectSortedMap , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final Long2ObjectSortedMap sortedMap; -+ protected UnmodifiableSortedMap( final Long2ObjectSortedMap m ) { -+ super( m ); -+ sortedMap = m; -+ } -+ public LongComparator comparator() { return sortedMap.comparator(); } -+ public ObjectSortedSet > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.long2ObjectEntrySet() ); return (ObjectSortedSet >)entries; } -+ @SuppressWarnings({ "rawtypes", "unchecked" }) -+ public ObjectSortedSet> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); } -+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.unmodifiable( sortedMap.keySet() ); return (LongSortedSet )keys; } -+ public Long2ObjectSortedMap subMap( final long from, final long to ) { return new UnmodifiableSortedMap ( sortedMap.subMap( from, to ) ); } -+ public Long2ObjectSortedMap headMap( final long to ) { return new UnmodifiableSortedMap ( sortedMap.headMap( to ) ); } -+ public Long2ObjectSortedMap tailMap( final long from ) { return new UnmodifiableSortedMap ( 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 subMap( final Long from, final Long to ) { return new UnmodifiableSortedMap ( sortedMap.subMap( from, to ) ); } -+ public Long2ObjectSortedMap headMap( final Long to ) { return new UnmodifiableSortedMap ( sortedMap.headMap( to ) ); } -+ public Long2ObjectSortedMap tailMap( final Long from ) { return new UnmodifiableSortedMap ( 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 Long2ObjectSortedMap unmodifiable( final Long2ObjectSortedMap m ) { return new UnmodifiableSortedMap ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

This class provides additional methods that implement a deque (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 null (FIFO queues have no comparator). -+ * @return null. -+ */ -+ @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 -+ * never 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. -+ * -+ *

This class implements the bulk methods removeElements(), -+ * addElements() and getElements() 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. -+ * -+ *

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 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 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. -+ * -+ *

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. -+ * -+ *

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 -+ * n, this method does nothing. Otherwise, it trims the -+ * array length to the maximum between n and {@link #size()}. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class represent a priority queue using a backing -+ * array—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. -+ * -+ *

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 null 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 null 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. -+ * -+ *

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 null 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. -+ * -+ *

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 null 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. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

It is responsibility of the caller that the elements of a 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 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. -+ * -+ *

It is responsibility of the caller that the first size elements of a are distinct. -+ * -+ * @param a the backing array. -+ * @param size the number of valid elements in a. -+ */ -+ 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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

In particular, the ensureCapacity(), grow(), -+ * trim() and setLength() methods allow to handle -+ * arrays much like array lists. This can be very useful when efficiency (or -+ * syntactic simplicity) reasons make array lists unsuitable. -+ * -+ *

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. -+ * -+ *

Sorting

-+ * -+ *

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 indirect sorting facility, which makes it possible -+ * to sort an array using the values in another array as comparator. -+ * -+ *

All comparison-based algorithm have an implementation based on a type-specific comparator. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

If you cannot foresee whether this array will need again to be -+ * enlarged, you should probably use grow() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it contains length entries or more; otherwise, -+ * an array with length entries whose first array.length -+ * entries are the same as those of array. -+ */ -+ 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 array, if it can contain length entries or more; otherwise, -+ * an array with length entries whose first preserve -+ * entries are the same as those of array. -+ */ -+ 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * array.length entries are the same as those of array. -+ * */ -+ 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() 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 array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * preserve entries are the same as those of array. -+ * */ -+ 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 array, if it contains length -+ * entries or less; otherwise, an array with -+ * length entries whose entries are the same as -+ * the first length entries of array. -+ * -+ */ -+ 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 array, if it contains exactly length -+ * entries; otherwise, if it contains more than -+ * length entries, an array with length entries -+ * whose entries are the same as the first length entries of -+ * array; otherwise, an array with length entries -+ * whose first array.length entries are the same as those of -+ * array. -+ * -+ */ -+ 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 length elements of array starting at offset. -+ */ -+ 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 array. -+ */ -+ 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. -+ * -+ *

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 from is greater than to. -+ * @throws ArrayIndexOutOfBoundsException if from or to 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. -+ * -+ *

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 length is negative. -+ * @throws ArrayIndexOutOfBoundsException if offset is negative or offset+length 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

This sort is guaranteed to be stable: 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 to 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: 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 to 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @param a the array to be sorted. -+ * @param from the index of the first element of perm (inclusive) to be permuted. -+ * @param to the index of the last element of perm (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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation uses a pool of {@link Runtime#availableProcessors()} threads. -+ * -+ * @param perm a permutation array indexing a. -+ * @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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ final int[] support = stable ? new int[ perm.length ] : null; -+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation uses a pool of {@link Runtime#availableProcessors()} threads. -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ *

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 queue = new LinkedBlockingQueue(); -+ 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 executorCompletionService = new ExecutorCompletionService( executorService ); -+ for ( int i = numberOfThreads; i-- != 0; ) -+ executorCompletionService.submit( new Callable() { -+ 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 a[ i ] < a[ i + 1 ] or a[ i ] == a[ i + 1 ] and b[ i ] ≤ b[ i + 1 ]. -+ * -+ *

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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a further support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]. -+ * -+ *

This implementation will allocate, in the stable case, a further support array as large as perm (note that the stable -+ * version is slightly faster). -+ * -+ * @param perm a permutation array indexing a. -+ * @param a the array to be sorted. -+ * @param b the second array to be sorted. -+ * @param from the index of the first element of perm (inclusive) to be permuted. -+ * @param to the index of the last element of perm (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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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. -+ * -+ *

The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas -+ * McIlroy, “Engineering radix sort”, Computing Systems, 6(1), pages 5−27 (1993). -+ * -+ *

This method implements a lexicographical 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 XorShift* generator). -+ * @return a. -+ */ -+ 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 XorShift* generator). -+ * @return a. -+ */ -+ 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 a. -+ */ -+ 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 a. -+ */ -+ 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, 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. -+ * -+ *

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 null correctly, and it is serializable. -+ */ -+ public final static Hash.Strategy 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * 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. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #previous()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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, LongIterable { -+ /** Returns a type-specific iterator on the elements of this collection. -+ * -+ *

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 fastutil 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. -+ * -+ *

Warning: 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[] 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. -+ * -+ *

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. -+ * -+ *

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 -+ * remove(). -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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[] 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 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 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[] 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Note that fastutil 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 { -+ /** 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 c. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 null for the natural order. -+ * @return the new position of the element of index i. -+ */ -+ -+ 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 null for the natural order. -+ * @return the new position of the element of index i. -+ */ -+ -+ 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 null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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()}. -+ * -+ *

Warning: Java will let you write “colon” for statements with primitive-type -+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an -+ * unboxing (and, in the case of fastutil type-specific data structures, a boxing) will be performed. Watch out. -+ * -+ * @see Iterable -+ */ -+public interface LongIterable extends Iterable { -+ /** 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * 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. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #next()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 element. -+ */ -+ 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. -+ * -+ *

The type-specific list iterator returned by this method will iterate -+ * length times, returning consecutive elements of the given -+ * array starting from the one with index offset. -+ * -+ * @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 length elements of array starting at position offset. -+ */ -+ 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. -+ * -+ *

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 array. -+ */ -+ 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. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of length, in the given array starting at offset. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and returns an array -+ * containing the elements returned by the iterator. At most max 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 max). -+ */ -+ -+ 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of max, in the given type-specific collection. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and adds -+ * the returned elements to the given collection (up to max). -+ * -+ * @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. -+ * -+ *

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. -+ * -+ *

This method iterates over the given type-specific iterator and returns -+ * a type-specific list containing the returned elements (up to max). 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 max. -+ */ -+ 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. -+ * -+ *

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 i; -+ public IteratorWrapper( final Iterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ @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 i; -+ public ListIteratorWrapper( final ListIterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ @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. -+ * -+ *

The type-specific bidirectional iterator returned by this method will return the -+ * elements from, from+1,…, to-1. -+ * -+ *

Note that all other type-specific interval iterator are list -+ * 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 from to to. -+ */ -+ 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. -+ * -+ *

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. -+ * -+ *

This method returns an iterator that will enumerate in order the elements returned -+ * by a[ offset ], then those returned -+ * by a[ offset + 1 ], and so on up to -+ * a[ offset + length - 1 ]. -+ * -+ * @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 length elements of a starting at offset. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

Additionally, this interface strengthens {@link #listIterator()}, -+ * {@link #listIterator(int)} and {@link #subList(int,int)}. -+ * -+ *

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, Comparable>, 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 fastutil 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 fastutil 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 from, inclusive, to the index to, exclusive. -+ * @see List#subList(int,int) -+ * @deprecated As of fastutil 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 from, inclusive, to the index to, exclusive. -+ * -+ *

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. -+ * -+ *

If the specified size is smaller than the current size, the last elements are -+ * discarded. Otherwise, they are filled with 0/null/false. -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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, 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 XorShift* generator). -+ * @return l. -+ */ -+ 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. -+ * -+ *

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 c ) { throw new UnsupportedOperationException(); } -+ public boolean addAll( int i, Collection 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 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. -+ * -+ *

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 c ) { throw new UnsupportedOperationException(); } -+ public boolean addAll( final int i, final Collection 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 element. -+ */ -+ 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 element. -+ */ -+ 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 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 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 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Instances of this class use a hash table to represent a set. The table is -+ * filled up to a specified load factor, and then doubled in size to -+ * accommodate new entries. If the table is emptied below one fourth -+ * 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. -+ * -+ *

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. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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. -+ * -+ *

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 fastutil 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 fastutil 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this set in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 never 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. -+ * -+ *

The actual table size will be the least power of two greater than expected/f. -+ * -+ * @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 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 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 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. -+ * -+ *

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 fastutil 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 fastutil 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

Let N be the smallest table size that can hold -+ * max(n,{@link #size()}) entries, still satisfying the load factor. If the current -+ * table size is smaller than or equal to N, this method does -+ * nothing. Otherwise, it rehashes this set in a table of size -+ * N. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

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 equals() 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this interface strengthens {@link #comparator()}. -+ */ -+public interface LongPriorityQueue extends PriorityQueue { -+ /** 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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this interface strengthens (again) {@link #iterator()}. -+ * -+ * @see Set -+ */ -+public interface LongSet extends LongCollection , Set { -+ /** Returns a type-specific iterator on the elements of this set. -+ * -+ *

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. -+ * -+ *

Note that the corresponding method of the type-specific collection is rem(). -+ * 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 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 element. -+ */ -+ 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 element. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 { -+ /** 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). -+ * -+ *

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 -+ * false). 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 false). -+ * -+ *

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. -+ * -+ *

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 fastutil 5, replaced by {@link #iterator()}. -+ */ -+ @Deprecated -+ LongBidirectionalIterator longIterator(); -+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in -+ * this set. -+ * -+ *

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 fromElement, inclusive, to toElement, exclusive. -+ * -+ *

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 toElement. -+ * -+ *

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 fromElement. -+ * -+ *

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. -+ * -+ *

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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

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 element. -+ */ -+ 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 element. -+ */ -+ 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 element. -+ */ -+ 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 element. -+ */ -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 { -+ /** -+ * @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 @@ -+ -+ -+ -+ fastutil -+ -+ -+ -+ -+

Provides type-specific classes for long elements or keys. -+ -+ -+ -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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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). -+ * -+ *

This class implements also a trivial version of {@link #back(int)} that -+ * uses type-specific methods. -+ */ -+public abstract class AbstractObjectBidirectionalIterator extends AbstractObjectIterator implements ObjectBidirectionalIterator { -+ protected AbstractObjectBidirectionalIterator() {} -+ /** This method just iterates the type-specific version of {@link #previous()} for -+ * at most n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

In particular, this class provide {@link #iterator()}, add(), {@link #remove(Object)} and -+ * {@link #contains(Object)} methods that just call the type-specific counterpart. -+ */ -+public abstract class AbstractObjectCollection extends AbstractCollection implements ObjectCollection { -+ 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[] 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 true if this collection changed as a result of the call. -+ */ -+ public boolean addAll( Collection c ) { -+ boolean retVal = false; -+ final Iterator 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 objectIterator() { -+ return iterator(); -+ } -+ public abstract ObjectIterator iterator(); -+ /** Checks whether this collection contains all elements from the given collection. -+ * -+ * @param c a collection. -+ * @return true 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 true 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 true 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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). -+ * -+ *

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 implements ObjectIterator { -+ 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 -+ * n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

As an additional bonus, this class implements on top of the list operations a type-specific stack. -+ */ -+public abstract class AbstractObjectList extends AbstractObjectCollection implements ObjectList , Stack { -+ 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 c ) { -+ ensureIndex( index ); -+ int n = c.size(); -+ if ( n == 0 ) return false; -+ Iterator i = c.iterator(); -+ while( n-- != 0 ) add( index++, i.next() ); -+ return true; -+ } -+ /** Delegates to a more generic method. */ -+ public boolean addAll( final Collection c ) { -+ return addAll( size(), c ); -+ } -+ /** Delegates to the new covariantly stronger generic method. */ -+ @Deprecated -+ public ObjectListIterator objectListIterator() { -+ return listIterator(); -+ } -+ /** Delegates to the new covariantly stronger generic method. */ -+ @Deprecated -+ public ObjectListIterator objectListIterator( final int index ) { -+ return listIterator( index ); -+ } -+ public ObjectListIterator iterator() { -+ return listIterator(); -+ } -+ public ObjectListIterator listIterator() { -+ return listIterator( 0 ); -+ } -+ public ObjectListIterator listIterator( final int index ) { -+ ensureIndex( index ); -+ return new AbstractObjectListIterator () { -+ 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 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 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 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 ( this, from, to ); -+ } -+ /** Delegates to the new covariantly stronger generic method. */ -+ @Deprecated -+ public ObjectList objectSubList( final int from, final int to ) { -+ return subList( from, to ); -+ } -+ /** Removes elements of this type-specific list one-by-one. -+ * -+ *

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 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. -+ * -+ *

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. -+ * -+ *

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 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 ClassCastException. -+ * -+ * @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 l ) { -+ if ( l == this ) return 0; -+ if ( l instanceof ObjectList ) { -+ final ObjectListIterator i1 = listIterator(), i2 = ((ObjectList )l).listIterator(); -+ int r; -+ K e1, e2; -+ while( i1.hasNext() && i2.hasNext() ) { -+ e1 = i1.next(); -+ e2 = i2.next(); -+ if ( ( r = ( ((Comparable)(e1)).compareTo(e2) ) ) != 0 ) return r; -+ } -+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 ); -+ } -+ ListIterator i1 = listIterator(), i2 = l.listIterator(); -+ int r; -+ while( i1.hasNext() && i2.hasNext() ) { -+ if ( ( r = ((Comparable)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 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 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 extends AbstractObjectList implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ /** The list this sublist restricts. */ -+ protected final ObjectList 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 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 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 listIterator( final int index ) { -+ ensureIndex( index ); -+ return new AbstractObjectListIterator () { -+ 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 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 ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 extends AbstractObjectBidirectionalIterator implements ObjectListIterator { -+ 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends AbstractObjectCollection implements Cloneable, ObjectSet { -+ protected AbstractObjectSet() {} -+ public abstract ObjectIterator 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 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends AbstractObjectSet implements ObjectSortedSet { -+ protected AbstractObjectSortedSet() {} -+ /** Delegates to the new covariantly stronger generic method. */ -+ @Deprecated -+ public ObjectBidirectionalIterator objectIterator() { -+ return iterator(); -+ } -+ public abstract ObjectBidirectionalIterator 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 -+ * never 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. 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. -+ * -+ *

This class implements the bulk methods removeElements(), -+ * addElements() and getElements() 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 extends AbstractObjectList 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 wrap(). 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. -+ * -+ *

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 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 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 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 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 i ) { -+ this(); -+ while( i.hasNext() ) this.add( i.next() ); -+ } -+ /** Returns the backing array of this list. -+ * -+ *

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). -+ * -+ *

Warning: This behaviour may cause (unfathomable) -+ * run-time errors if a method expects an array -+ * actually of type K[], 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. -+ * -+ *

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 ObjectArrayList 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 l = new ObjectArrayList ( a, false ); -+ l.size = length; -+ return l; -+ } -+ /** Wraps a given array into an array list. -+ * -+ *

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 ObjectArrayList 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 -+ * n, this method does nothing. Otherwise, it trims the -+ * array length to the maximum between n and {@link #size()}. -+ * -+ *

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 listIterator( final int index ) { -+ ensureIndex( index ); -+ return new AbstractObjectListIterator () { -+ 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 clone() { -+ ObjectArrayList c = new ObjectArrayList ( 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. -+ * -+ *

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 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. -+ * -+ *

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 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)(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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends AbstractObjectSet 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. -+ * -+ *

It is responsibility of the caller that the elements of a 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 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 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. -+ * -+ *

It is responsibility of the caller that the first size elements of a are distinct. -+ * -+ * @param a the backing array. -+ * @param size the number of valid elements in a. -+ */ -+ 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 iterator() { -+ return new AbstractObjectIterator () { -+ 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. -+ * -+ *

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 clone() { -+ ObjectArraySet c; -+ try { -+ c = (ObjectArraySet )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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 ensureCapacity(), grow(), -+ * trim() and setLength() methods allow to handle -+ * arrays much like array lists. This can be very useful when efficiency (or -+ * syntactic simplicity) reasons make array lists unsuitable. -+ * -+ *

Warning: 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 significantly slower than using new. -+ * This phenomenon is particularly -+ * evident in the first growth phases of an array reallocated with doubling (or similar) logic. -+ * -+ *

Sorting

-+ * -+ *

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}. -+ * -+ *

All comparison-based algorithm have an implementation based on a type-specific comparator. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

This method returns a new array of the given length whose element -+ * are of the same class as of those of prototype. 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[] 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. -+ * -+ *

If you cannot foresee whether this array will need again to be -+ * enlarged, you should probably use grow() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it contains length entries or more; otherwise, -+ * an array with length entries whose first array.length -+ * entries are the same as those of array. -+ */ -+ public static 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 array, if it can contain length entries or more; otherwise, -+ * an array with length entries whose first preserve -+ * entries are the same as those of array. -+ */ -+ public static 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() instead. -+ * -+ * @param array an array. -+ * @param length the new minimum length for this array. -+ * @return array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * array.length entries are the same as those of array. -+ * */ -+ public static 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. -+ * -+ *

If you want complete control on the array growth, you -+ * should probably use ensureCapacity() 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 array, if it can contain length -+ * entries; otherwise, an array with -+ * max(length,array.length/φ) entries whose first -+ * preserve entries are the same as those of array. -+ * */ -+ public static 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 array, if it contains length -+ * entries or less; otherwise, an array with -+ * length entries whose entries are the same as -+ * the first length entries of array. -+ * -+ */ -+ public static 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 array, if it contains exactly length -+ * entries; otherwise, if it contains more than -+ * length entries, an array with length entries -+ * whose entries are the same as the first length entries of -+ * array; otherwise, an array with length entries -+ * whose first array.length entries are the same as those of -+ * array. -+ * -+ */ -+ public static 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 length elements of array starting at offset. -+ */ -+ public static 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 array. -+ */ -+ public static 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 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 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 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. -+ * -+ *

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 from is greater than to. -+ * @throws ArrayIndexOutOfBoundsException if from or to are greater than the array length or negative. -+ */ -+ public static 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. -+ * -+ *

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 length is negative. -+ * @throws ArrayIndexOutOfBoundsException if offset is negative or offset+length is greater than the array length. -+ */ -+ public static 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 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 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 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 int med3( final K x[], final int a, final int b, final int c, Comparator 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 K[] a, final int from, final int to, final Comparator 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 void insertionSort( final K[] a, final int from, final int to, final Comparator 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] x, final int from, final int to, final Comparator 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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] x, final Comparator 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 K[] x; -+ private final Comparator comp; -+ public ForkJoinQuickSortComp( final K[] x , final int from , final int to, final Comparator 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* -+ 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] x, final int from, final int to, final Comparator 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] x, final Comparator comp ) { -+ parallelQuickSort( x, 0, x.length, comp ); -+ } -+ @SuppressWarnings("unchecked") -+ private static int med3( final K x[], final int a, final int b, final int c ) { -+ final int ab = ( ((Comparable)(x[ a ])).compareTo(x[ b ]) ); -+ final int ac = ( ((Comparable)(x[ a ])).compareTo(x[ c ]) ); -+ final int bc = ( ((Comparable)(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 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)(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 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)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while(true) { -+ int comparison; -+ while ( b <= c && ( comparison = ( ((Comparable)(x[ b ])).compareTo(v) ) ) <= 0 ) { -+ if ( comparison == 0 ) swap( x, a++, b ); -+ b++; -+ } -+ while (c >= b && ( comparison = ( ((Comparable)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] 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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while ( true ) { -+ int comparison; -+ while ( b <= c && ( comparison = ( ((Comparable)(x[ b ])).compareTo(v) ) ) <= 0 ) { -+ if ( comparison == 0 ) swap( x, a++, b ); -+ b++; -+ } -+ while ( c >= b && ( comparison = ( ((Comparable)(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 ( 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 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 ( x, from, to ) ); -+ pool.shutdown(); -+ } -+ } -+ /** Sorts an array according to the natural ascending order using a parallel quicksort. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

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 K[] x ) { -+ parallelQuickSort( x, 0, x.length ); -+ } -+ @SuppressWarnings("unchecked") -+ private static 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)(aa)).compareTo(bb) ); -+ final int ac = ( ((Comparable)(aa)).compareTo(cc) ); -+ final int bc = ( ((Comparable)(bb)).compareTo(cc) ); -+ return ( ab < 0 ? -+ ( bc < 0 ? b : ac < 0 ? c : a ) : -+ ( bc > 0 ? b : ac > 0 ? c : a ) ); -+ } -+ @SuppressWarnings("unchecked") -+ private static 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)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while(true) { -+ int comparison; -+ while ( b <= c && ( comparison = ( ((Comparable)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) { -+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b ); -+ b++; -+ } -+ while (c >= b && ( comparison = ( ((Comparable)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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 K[] 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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while ( true ) { -+ int comparison; -+ while ( b <= c && ( comparison = ( ((Comparable)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) { -+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b ); -+ b++; -+ } -+ while ( c >= b && ( comparison = ( ((Comparable)(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 ( 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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 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 ( perm, x, from, to ) ); -+ pool.shutdown(); -+ } -+ } -+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implement an indirect sort. The elements of perm (which must -+ * be exactly the numbers in the interval [0..perm.length)) will be permuted so that -+ * x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]. -+ * -+ *

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 K[] x ) { -+ parallelQuickSortIndirect( perm, x, 0, x.length ); -+ } -+ /** Stabilizes a permutation. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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 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. -+ * -+ *

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. -+ * -+ *

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. -+ * -+ *

More precisely, assuming that x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ], after -+ * stabilization we will also have that x[ perm[ i ] ] = x[ perm[ i + 1 ] ] implies -+ * perm[ i ] ≤ perm[ i + 1 ]. -+ * -+ * @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 K[] x ) { -+ stabilize( perm, x, 0, perm.length ); -+ } -+ @SuppressWarnings("unchecked") -+ private static int med3( final K x[], final K[] y, final int a, final int b, final int c ) { -+ int t; -+ final int ab = ( t = ( ((Comparable)(x[ a ])).compareTo(x[ b ]) ) ) == 0 ? ( ((Comparable)(y[ a ])).compareTo(y[ b ]) ) : t; -+ final int ac = ( t = ( ((Comparable)(x[ a ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable)(y[ a ])).compareTo(y[ c ]) ) : t; -+ final int bc = ( t = ( ((Comparable)(x[ b ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable)(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 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 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 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)(a[ j ])).compareTo(a[ m ]) ) ) < 0 || u == 0 && ( ((Comparable)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while ( true ) { -+ int comparison, t; -+ while ( b <= c && ( comparison = ( t = ( ((Comparable)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable)(y[ b ])).compareTo(w) ) : t ) <= 0 ) { -+ if ( comparison == 0 ) swap( x, y, a++, b ); -+ b++; -+ } -+ while ( c >= b && ( comparison = ( t = ( ((Comparable)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable)(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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ * @param x the first array to be sorted. -+ * @param y the second array to be sorted. -+ */ -+ public static void quickSort( final K[] x, final K[] 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 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* -+ int a = from, b = a, c = to - 1, d = c; -+ while ( true ) { -+ int comparison, t; -+ while ( b <= c && ( comparison = ( t = ( ((Comparable)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable)(y[ b ])).compareTo(w) ) : t ) <= 0 ) { -+ if ( comparison == 0 ) swap( x, y, a++, b ); -+ b++; -+ } -+ while ( c >= b && ( comparison = ( t = ( ((Comparable)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable)(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 ( 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. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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 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 ( x, y, from, to ) ); -+ pool.shutdown(); -+ } -+ /** Sorts two arrays according to the natural lexicographical -+ * ascending order using a parallel quicksort. -+ * -+ *

The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas -+ * McIlroy, “Engineering a Sort Function”, Software: Practice and Experience, 23(11), pages -+ * 1249−1265, 1993. -+ * -+ *

This method implements a lexicographical 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 x[ i ] < x[ i + 1 ] or x[ i ] -+ * == x[ i + 1 ] and y[ i ] ≤ y[ i + 1 ]. -+ * -+ *

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 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. -+ * -+ *

This sort is guaranteed to be stable: 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 to elements, and whose entries are identical to those -+ * of {@code a} in the specified range. -+ */ -+ @SuppressWarnings("unchecked") -+ public static 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)(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)(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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a will be allocated by this method. -+ -+ * @param a the array to be sorted. -+ */ -+ public static 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. -+ * -+ *

This sort is guaranteed to be stable: 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 to elements, and whose entries are identical to those -+ * of {@code a} in the specified range. -+ */ -+ public static void mergeSort( final K a[], final int from, final int to, Comparator 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. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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 K a[], final int from, final int to, Comparator comp ) { -+ mergeSort( a, from, to, comp, a.clone() ); -+ } -+ /** Sorts an array according to the order induced by the specified -+ * comparator using mergesort. -+ * -+ *

This sort is guaranteed to be stable: equal elements will not be reordered as a result -+ * of the sort. An array as large as a 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 K a[], Comparator 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 0 if -+ * and only if the key is found. -+ * @see java.util.Arrays -+ */ -+ @SuppressWarnings("unchecked") -+ public static 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 )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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 0 if -+ * and only if the key is found. -+ * @see java.util.Arrays -+ */ -+ public static 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 0 if -+ * and only if the key is found. -+ * @see java.util.Arrays -+ */ -+ public static int binarySearch( final K[] a, int from, int to, final K key, final Comparator 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, (-(insertion point) - 1). The insertion -+ * point 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 ≥ 0 if -+ * and only if the key is found. -+ * @see java.util.Arrays -+ */ -+ public static int binarySearch( final K[] a, final K key, final Comparator 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 XorShift* generator). -+ * @return a. -+ */ -+ public static 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 XorShift* generator). -+ * @return a. -+ */ -+ public static 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 a. -+ */ -+ public static 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 a. -+ */ -+ public static 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 implements Hash.Strategy, 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. -+ * -+ *

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 null 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends ObjectIterator , BidirectionalIterator { -+ /** Moves back for the given number of elements. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #previous()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this class defines strengthens (again) {@link #iterator()} and defines -+ * a slightly different semantics for {@link #toArray(Object[])}. -+ * -+ * @see Collection -+ */ -+public interface ObjectCollection extends Collection, ObjectIterable { -+ /** Returns a type-specific iterator on the elements of this collection. -+ * -+ *

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 iterator(); -+ /** Returns a type-specific iterator on this elements of this collection. -+ * -+ * @see #iterator() -+ * @deprecated As of fastutil 5, replaced by {@link #iterator()}. -+ */ -+ @Deprecated -+ ObjectIterator objectIterator(); -+ /** Returns an containing the items of this collection; -+ * the runtime type of the returned array is that of the specified array. -+ * -+ *

Warning: 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[] 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific collection. -+ */ -+ public abstract static class EmptyCollection extends AbstractObjectCollection { -+ 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[] toArray( T[] a ) { return a; } -+ @SuppressWarnings("unchecked") -+ public ObjectBidirectionalIterator 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 implements ObjectCollection , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final ObjectCollection collection; -+ protected final Object sync; -+ protected SynchronizedCollection( final ObjectCollection c, final Object sync ) { -+ if ( c == null ) throw new NullPointerException(); -+ this.collection = c; -+ this.sync = sync; -+ } -+ protected SynchronizedCollection( final ObjectCollection 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[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } } -+ public ObjectIterator iterator() { return collection.iterator(); } -+ @Deprecated -+ public ObjectIterator 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 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 ObjectCollection synchronize( final ObjectCollection 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 ObjectCollection synchronize( final ObjectCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); } -+ /** An unmodifiable wrapper class for collections. */ -+ public static class UnmodifiableCollection implements ObjectCollection , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final ObjectCollection collection; -+ protected UnmodifiableCollection( final ObjectCollection 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 iterator() { return ObjectIterators.unmodifiable( collection.iterator() ); } -+ @Deprecated -+ public ObjectIterator 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 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[] 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 ObjectCollection unmodifiable( final ObjectCollection c ) { return new UnmodifiableCollection ( c ); } -+ /** A collection wrapper class for iterables. */ -+ public static class IterableCollection extends AbstractObjectCollection implements java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final ObjectIterable iterable; -+ protected IterableCollection( final ObjectIterable iterable ) { -+ if ( iterable == null ) throw new NullPointerException(); -+ this.iterable = iterable; -+ } -+ public int size() { -+ int c = 0; -+ final ObjectIterator iterator = iterator(); -+ while( iterator.hasNext() ) { -+ iterator.next(); -+ c++; -+ } -+ return c; -+ } -+ public boolean isEmpty() { return iterable.iterator().hasNext(); } -+ public ObjectIterator iterator() { return iterable.iterator(); } -+ @Deprecated -+ public ObjectIterator 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 ObjectCollection asCollection( final ObjectIterable iterable ) { -+ if ( iterable instanceof ObjectCollection ) return (ObjectCollection )iterable; -+ return new IterableCollection ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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()}. -+ * -+ *

Warning: Java will let you write “colon” for statements with primitive-type -+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an -+ * unboxing (and, in the case of fastutil type-specific data structures, a boxing) will be performed. Watch out. -+ * -+ * @see Iterable -+ */ -+public interface ObjectIterable extends Iterable { -+ /** Returns a type-specific iterator. -+ * -+ * Note that this specification strengthens the one given in {@link Iterable#iterator()}. -+ * -+ * @return a type-specific iterator. -+ */ -+ ObjectIterator 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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 extends Iterator { -+ /** Skips the given number of elements. -+ * -+ *

The effect of this call is exactly the same as that of -+ * calling {@link #next()} for n 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific iterator. -+ */ -+ public static class EmptyIterator extends AbstractObjectListIterator 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. -+ * -+ *

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 extends AbstractObjectListIterator { -+ 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 element. -+ */ -+ public static ObjectListIterator singleton( final K element ) { -+ return new SingletonIterator ( element ); -+ } -+ /** A class to wrap arrays in iterators. */ -+ private static class ArrayIterator extends AbstractObjectListIterator { -+ 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. -+ * -+ *

The type-specific list iterator returned by this method will iterate -+ * length times, returning consecutive elements of the given -+ * array starting from the one with index offset. -+ * -+ * @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 length elements of array starting at position offset. -+ */ -+ public static ObjectListIterator wrap( final K[] array, final int offset, final int length ) { -+ ObjectArrays.ensureOffsetLength( array, offset, length ); -+ return new ArrayIterator ( array, offset, length ); -+ } -+ /** Wraps the given array into a type-specific list iterator. -+ * -+ *

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 array. -+ */ -+ public static ObjectListIterator wrap( final K[] 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. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of length, in the given array starting at offset. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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 Iterator 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. -+ * -+ *

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 Iterator 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. -+ * -+ *

This method iterates over the given type-specific iterator and returns an array -+ * containing the elements returned by the iterator. At most max 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 max). -+ */ -+ @SuppressWarnings("unchecked") -+ public static K[] unwrap( final Iterator 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. -+ * -+ *

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[] unwrap( final Iterator i ) { -+ return unwrap( i, Integer.MAX_VALUE ); -+ } -+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements. -+ * -+ *

This method iterates over the given type-specific iterator and stores the elements -+ * returned, up to a maximum of max, in the given type-specific collection. -+ * The number of actually unwrapped elements is returned (it may be less than max if -+ * the iterator emits less than max 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 Iterator i, final ObjectCollection 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. -+ * -+ *

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 Iterator i, final ObjectCollection 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. -+ * -+ *

This method iterates over the given type-specific iterator and adds -+ * the returned elements to the given collection (up to max). -+ * -+ * @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 Iterator i, final ObjectCollection 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. -+ * -+ *

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 Iterator i, final ObjectCollection s ) { -+ return pour( i, s, Integer.MAX_VALUE ); -+ } -+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements. -+ * -+ *

This method iterates over the given type-specific iterator and returns -+ * a type-specific list containing the returned elements (up to max). 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 max. -+ */ -+ public static ObjectList pour( final Iterator i, int max ) { -+ final ObjectArrayList l = new ObjectArrayList (); -+ pour( i, l, max ); -+ l.trim(); -+ return l; -+ } -+ /** Pours an iterator, returning a type-specific list. -+ * -+ *

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 ObjectList pour( final Iterator i ) { -+ return pour( i, Integer.MAX_VALUE ); -+ } -+ private static class IteratorWrapper extends AbstractObjectIterator { -+ final Iterator i; -+ public IteratorWrapper( final Iterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ public static ObjectIterator asObjectIterator( final Iterator i ) { -+ if ( i instanceof ObjectIterator ) return (ObjectIterator )i; -+ return new IteratorWrapper ( i ); -+ } -+ private static class ListIteratorWrapper extends AbstractObjectListIterator { -+ final ListIterator i; -+ public ListIteratorWrapper( final ListIterator 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. -+ * -+ *

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 i: changes to one of the iterators -+ * will affect the other, too. -+ * -+ *

If i 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 i. -+ */ -+ public static ObjectListIterator asObjectIterator( final ListIterator i ) { -+ if ( i instanceof ObjectListIterator ) return (ObjectListIterator )i; -+ return new ListIteratorWrapper ( i ); -+ } -+ private static class IteratorConcatenator extends AbstractObjectIterator { -+ final ObjectIterator a[]; -+ int offset, length, lastOffset = -1; -+ public IteratorConcatenator( final ObjectIterator 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. -+ * -+ *

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 ObjectIterator concat( final ObjectIterator a[] ) { -+ return concat( a, 0, a.length ); -+ } -+ /** Concatenates a sequence of iterators contained in an array. -+ * -+ *

This method returns an iterator that will enumerate in order the elements returned -+ * by a[ offset ], then those returned -+ * by a[ offset + 1 ], and so on up to -+ * a[ offset + length - 1 ]. -+ * -+ * @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 length elements of a starting at offset. -+ */ -+ public static ObjectIterator concat( final ObjectIterator a[], final int offset, final int length ) { -+ return new IteratorConcatenator ( a, offset, length ); -+ } -+ /** An unmodifiable wrapper class for iterators. */ -+ public static class UnmodifiableIterator extends AbstractObjectIterator { -+ final protected ObjectIterator i; -+ public UnmodifiableIterator( final ObjectIterator 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 ObjectIterator unmodifiable( final ObjectIterator i ) { return new UnmodifiableIterator ( i ); } -+ /** An unmodifiable wrapper class for bidirectional iterators. */ -+ public static class UnmodifiableBidirectionalIterator extends AbstractObjectBidirectionalIterator { -+ final protected ObjectBidirectionalIterator i; -+ public UnmodifiableBidirectionalIterator( final ObjectBidirectionalIterator 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 ObjectBidirectionalIterator unmodifiable( final ObjectBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); } -+ /** An unmodifiable wrapper class for list iterators. */ -+ public static class UnmodifiableListIterator extends AbstractObjectListIterator { -+ final protected ObjectListIterator i; -+ public UnmodifiableListIterator( final ObjectListIterator 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 ObjectListIterator unmodifiable( final ObjectListIterator i ) { return new UnmodifiableListIterator ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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. -+ * -+ *

Additionally, this interface strengthens {@link #listIterator()}, -+ * {@link #listIterator(int)} and {@link #subList(int,int)}. -+ * -+ *

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 extends List, Comparable>, ObjectCollection { -+ /** 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 iterator(); -+ /** Returns a type-specific list iterator on the list. -+ * -+ * @see #listIterator() -+ * @deprecated As of fastutil 5, replaced by {@link #listIterator()}. -+ */ -+ @Deprecated -+ ObjectListIterator objectListIterator(); -+ /** Returns a type-specific list iterator on the list starting at a given index. -+ * -+ * @see #listIterator(int) -+ * @deprecated As of fastutil 5, replaced by {@link #listIterator(int)}. -+ */ -+ @Deprecated -+ ObjectListIterator objectListIterator( int index ); -+ /** Returns a type-specific list iterator on the list. -+ * -+ * @see List#listIterator() -+ */ -+ ObjectListIterator listIterator(); -+ /** Returns a type-specific list iterator on the list starting at a given index. -+ * -+ * @see List#listIterator(int) -+ */ -+ ObjectListIterator listIterator( int index ); -+ /** Returns a type-specific view of the portion of this list from the index from, inclusive, to the index to, exclusive. -+ * @see List#subList(int,int) -+ * @deprecated As of fastutil 5, replaced by {@link #subList(int,int)}. -+ */ -+ @Deprecated -+ ObjectList objectSubList( int from, int to ); -+ /** Returns a type-specific view of the portion of this list from the index from, inclusive, to the index to, exclusive. -+ * -+ *

Note that this specification strengthens the one given in {@link List#subList(int,int)}. -+ * -+ * @see List#subList(int,int) -+ */ -+ ObjectList subList(int from, int to); -+ /** Sets the size of this list. -+ * -+ *

If the specified size is smaller than the current size, the last elements are -+ * discarded. Otherwise, they are filled with 0/null/false. -+ * -+ * @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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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}. -+ * -+ *

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 extends ListIterator, ObjectBidirectionalIterator { -+} -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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

Additionally, this interface strengthens (again) {@link #iterator()}. -+ * -+ * @see Set -+ */ -+public interface ObjectSet extends ObjectCollection , Set { -+ /** Returns a type-specific iterator on the elements of this set. -+ * -+ *

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 iterator(); -+ /** Removes an element from this set. -+ * -+ *

Note that the corresponding method of the type-specific collection is rem(). -+ * 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific set. -+ */ -+ public static class EmptySet extends ObjectCollections.EmptyCollection implements ObjectSet , 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_SET}. -+ * @return an empty set (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static ObjectSet emptySet() { -+ return EMPTY_SET; -+ } -+ /** An immutable class representing a type-specific singleton set. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific set. */ -+ public static class Singleton extends AbstractObjectSet 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 c ) { throw new UnsupportedOperationException(); } -+ public boolean removeAll( final Collection c ) { throw new UnsupportedOperationException(); } -+ public boolean retainAll( final Collection c ) { throw new UnsupportedOperationException(); } -+ public ObjectListIterator 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 element. -+ */ -+ public static ObjectSet singleton( final K element ) { -+ return new Singleton ( element ); -+ } -+ /** A synchronized wrapper class for sets. */ -+ public static class SynchronizedSet extends ObjectCollections.SynchronizedCollection implements ObjectSet , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected SynchronizedSet( final ObjectSet s, final Object sync ) { -+ super( s, sync ); -+ } -+ protected SynchronizedSet( final ObjectSet 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 ObjectSet synchronize( final ObjectSet 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 ObjectSet synchronize( final ObjectSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); } -+ /** An unmodifiable wrapper class for sets. */ -+ public static class UnmodifiableSet extends ObjectCollections.UnmodifiableCollection implements ObjectSet , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected UnmodifiableSet( final ObjectSet 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 ObjectSet unmodifiable( final ObjectSet s ) { return new UnmodifiableSet ( 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

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 extends ObjectSet , SortedSet { -+ /** 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). -+ * -+ *

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 -+ * false). 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 false). -+ * -+ *

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 iterator( K fromElement ); -+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection. -+ * -+ *

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 fastutil 5, replaced by {@link #iterator()}. -+ */ -+ @Deprecated -+ ObjectBidirectionalIterator objectIterator(); -+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in -+ * this set. -+ * -+ *

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 iterator(); -+ /** Returns a view of the portion of this sorted set whose elements range from fromElement, inclusive, to toElement, exclusive. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}. -+ * -+ * @see SortedSet#subSet(Object,Object) -+ */ -+ ObjectSortedSet subSet( K fromElement, K toElement) ; -+ /** Returns a view of the portion of this sorted set whose elements are strictly less than toElement. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}. -+ * -+ * @see SortedSet#headSet(Object) -+ */ -+ ObjectSortedSet headSet( K toElement ); -+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to fromElement. -+ * -+ *

Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}. -+ * -+ * @see SortedSet#tailSet(Object) -+ */ -+ ObjectSortedSet 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 -+ . */ -+/* This header is separate from features.h so that the compiler can -+ include it implicitly at the start of every compilation. It must -+ not itself include or any other header that includes -+ because the implicit include comes before any feature -+ test macros that may be defined in a source file before it first -+ explicitly includes a system header. GCC knows the name of this -+ header in order to preinclude it. */ -+/* glibc's intent is to support the IEC 559 math functionality, real -+ and complex. If the GCC (4.9 and later) predefined macros -+ specifying compiler intent are available, use them to determine -+ whether the overall intent is to support these features; otherwise, -+ presume an older compiler has intent to support these features and -+ define these macros by default. */ -+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) / -+ Unicode 6.0. */ -+/* We do not support C11 . */ -+/* Generic definitions */ -+/* Assertions (useful to generate conditional code) */ -+/* Current type and class (and size, if applicable) */ -+/* Value methods */ -+/* Interfaces (keys) */ -+/* Interfaces (values) */ -+/* Abstract implementations (keys) */ -+/* Abstract implementations (values) */ -+/* Static containers (keys) */ -+/* Static containers (values) */ -+/* Implementations */ -+/* Synchronized wrappers */ -+/* Unmodifiable wrappers */ -+/* Other wrappers */ -+/* Methods (keys) */ -+/* Methods (values) */ -+/* 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. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted set. -+ */ -+ public static class EmptySet extends ObjectSets.EmptySet implements ObjectSortedSet , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected EmptySet() {} -+ public boolean remove( Object ok ) { throw new UnsupportedOperationException(); } -+ @Deprecated -+ public ObjectBidirectionalIterator objectIterator() { return iterator(); } -+ @SuppressWarnings("unchecked") -+ public ObjectBidirectionalIterator iterator( K from ) { return ObjectIterators.EMPTY_ITERATOR; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet subSet( K from, K to ) { return EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet headSet( K from ) { return EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet tailSet( K to ) { return EMPTY_SET; } -+ public K first() { throw new NoSuchElementException(); } -+ public K last() { throw new NoSuchElementException(); } -+ public Comparator 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. -+ * -+ *

This method provides a typesafe access to {@link #EMPTY_SET}. -+ * @return an empty sorted set (immutable). -+ */ -+ @SuppressWarnings("unchecked") -+ public static ObjectSet emptySet() { -+ return EMPTY_SET; -+ } -+ /** A class representing a singleton sorted set. -+ * -+ *

This class may be useful to implement your own in case you subclass -+ * a type-specific sorted set. -+ */ -+ public static class Singleton extends ObjectSets.Singleton implements ObjectSortedSet , java.io.Serializable, Cloneable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ final Comparator comparator; -+ private Singleton( final K element, final Comparator 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)(k1)).compareTo(k2) ) : comparator.compare( k1, k2 ); -+ } -+ @Deprecated -+ public ObjectBidirectionalIterator objectIterator() { -+ return iterator(); -+ } -+ public ObjectBidirectionalIterator iterator( K from ) { -+ ObjectBidirectionalIterator i = iterator(); -+ if ( compare( element, from ) <= 0 ) i.next(); -+ return i; -+ } -+ public Comparator comparator() { return comparator; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet 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 headSet( final K to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; } -+ @SuppressWarnings("unchecked") -+ public ObjectSortedSet 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 element. -+ */ -+ public static ObjectSortedSet singleton( final K 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 element. -+ */ -+ public static ObjectSortedSet singleton( final K element, final Comparator comparator ) { -+ return new Singleton ( element, comparator ); -+ } -+ /** A synchronized wrapper class for sorted sets. */ -+ public static class SynchronizedSortedSet extends ObjectSets.SynchronizedSet implements ObjectSortedSet , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final ObjectSortedSet sortedSet; -+ protected SynchronizedSortedSet( final ObjectSortedSet s, final Object sync ) { -+ super( s, sync ); -+ sortedSet = s; -+ } -+ protected SynchronizedSortedSet( final ObjectSortedSet s ) { -+ super( s ); -+ sortedSet = s; -+ } -+ public Comparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } } -+ public ObjectSortedSet subSet( final K from, final K to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); } -+ public ObjectSortedSet headSet( final K to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); } -+ public ObjectSortedSet tailSet( final K from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); } -+ public ObjectBidirectionalIterator iterator() { return sortedSet.iterator(); } -+ public ObjectBidirectionalIterator iterator( final K from ) { return sortedSet.iterator( from ); } -+ @Deprecated -+ public ObjectBidirectionalIterator 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 ObjectSortedSet synchronize( final ObjectSortedSet 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 ObjectSortedSet synchronize( final ObjectSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); } -+ /** An unmodifiable wrapper class for sorted sets. */ -+ public static class UnmodifiableSortedSet extends ObjectSets.UnmodifiableSet implements ObjectSortedSet , java.io.Serializable { -+ private static final long serialVersionUID = -7046029254386353129L; -+ protected final ObjectSortedSet sortedSet; -+ protected UnmodifiableSortedSet( final ObjectSortedSet s ) { -+ super( s ); -+ sortedSet = s; -+ } -+ public Comparator comparator() { return sortedSet.comparator(); } -+ public ObjectSortedSet subSet( final K from, final K to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); } -+ public ObjectSortedSet headSet( final K to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); } -+ public ObjectSortedSet tailSet( final K from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); } -+ public ObjectBidirectionalIterator iterator() { return ObjectIterators.unmodifiable( sortedSet.iterator() ); } -+ public ObjectBidirectionalIterator iterator( final K from ) { return ObjectIterators.unmodifiable( sortedSet.iterator( from ) ); } -+ @Deprecated -+ public ObjectBidirectionalIterator 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 ObjectSortedSet unmodifiable( final ObjectSortedSet s ) { return new UnmodifiableSortedSet ( s ); } -+} --- -2.8.0 - diff --git a/Spigot-API-Patches/0002-add-Trove-and-FastUtil-to-Bukkit.patch b/Spigot-API-Patches/0002-add-Trove-and-FastUtil-to-Bukkit.patch new file mode 100644 index 000000000..df25c2573 --- /dev/null +++ b/Spigot-API-Patches/0002-add-Trove-and-FastUtil-to-Bukkit.patch @@ -0,0 +1,33 @@ +From 95be64b105c7cc5e412441b55ef5257a9aacb660 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Fri, 1 Apr 2016 00:02:47 -0400 +Subject: [PATCH] add Trove and FastUtil to Bukkit + + +diff --git a/pom.xml b/pom.xml +index a03865f..597f65c 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -48,6 +48,19 @@ + + + ++ net.sf.trove4j ++ trove4j ++ 3.0.3 ++ ++ provided ++ ++ ++ co.aikar ++ fastutil-lite ++ 1.0 ++ provided ++ ++ + commons-lang + commons-lang + 2.6 +-- +2.8.0 + diff --git a/Spigot-API-Patches/0003-Timings-v2.patch b/Spigot-API-Patches/0003-Timings-v2.patch index 941ed5660..1a2030edd 100644 --- a/Spigot-API-Patches/0003-Timings-v2.patch +++ b/Spigot-API-Patches/0003-Timings-v2.patch @@ -1,32 +1,9 @@ -From c06ec1a9abc604b79f3c0e282ca752814de91110 Mon Sep 17 00:00:00 2001 +From ec3f78348b95c24b1e62101a871c43136432f5bb Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 29 Feb 2016 18:48:17 -0600 Subject: [PATCH] Timings v2 -diff --git a/pom.xml b/pom.xml -index d916f44..d3a877a 100644 ---- a/pom.xml -+++ b/pom.xml -@@ -1,4 +1,3 @@ -- - - 4.0.0 -@@ -48,6 +47,13 @@ - - - -+ net.sf.trove4j -+ trove4j -+ 3.0.3 -+ -+ provided -+ -+ - commons-lang - commons-lang - 2.6 diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java new file mode 100644 index 0000000..cb4e7ba diff --git a/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch index 01ce28e4a..6242d2a21 100644 --- a/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch +++ b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch @@ -1,4 +1,4 @@ -From e5e95709d29d23cb34387060e95de1aad352e432 Mon Sep 17 00:00:00 2001 +From 4c640a3a8199ea1b1653e9e03e65e4b6af3b4697 Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 3 Mar 2016 13:20:33 -0700 Subject: [PATCH] Use ASM for event executors. @@ -6,10 +6,10 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/pom.xml b/pom.xml -index d3a877a..92a729b 100644 +index 597f65c..58ddcf3 100644 --- a/pom.xml +++ b/pom.xml -@@ -112,6 +112,12 @@ +@@ -119,6 +119,12 @@ 1.3 test diff --git a/Spigot-Server-Patches/0005-Timings-v2.patch b/Spigot-Server-Patches/0005-Timings-v2.patch index 732858904..29bed0e89 100644 --- a/Spigot-Server-Patches/0005-Timings-v2.patch +++ b/Spigot-Server-Patches/0005-Timings-v2.patch @@ -1,9 +1,26 @@ -From a2bec60dd78b081c7ad0a82fb03aee52dbab9284 Mon Sep 17 00:00:00 2001 +From 4979dcfaf9eb2d1d5b3533c429347ab0670e85aa Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 3 Mar 2016 04:00:11 -0600 Subject: [PATCH] Timings v2 +diff --git a/pom.xml b/pom.xml +index 8899e3a..3685721 100644 +--- a/pom.xml ++++ b/pom.xml +@@ -65,6 +65,12 @@ + compile + + ++ co.aikar ++ fastutil-lite ++ 1.0 ++ provided ++ ++ + net.sf.trove4j + trove4j + 3.0.3 diff --git a/src/main/java/co/aikar/timings/SpigotTimings.java b/src/main/java/co/aikar/timings/SpigotTimings.java new file mode 100644 index 0000000..3f4271c diff --git a/Spigot-Server-Patches/0055-EAR-Fix-bug-with-teleporting-entities.patch b/Spigot-Server-Patches/0055-EAR-Fix-bug-with-teleporting-entities.patch index dc5b97b00..65b7591f5 100644 --- a/Spigot-Server-Patches/0055-EAR-Fix-bug-with-teleporting-entities.patch +++ b/Spigot-Server-Patches/0055-EAR-Fix-bug-with-teleporting-entities.patch @@ -1,4 +1,4 @@ -From 81633282d869e155958c376e88e245dc6f645bd0 Mon Sep 17 00:00:00 2001 +From 1d3116bd0f65f50f5b1fbfffa4d042cbc85cbb98 Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 3 Mar 2016 00:07:23 -0600 Subject: [PATCH] EAR: Fix bug with teleporting entities @@ -31,6 +31,19 @@ index 782abd6..359e18e 100644 public boolean ah; public boolean impulse; public int portalCooldown; +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index bffa3ac..1a1f082 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -1623,7 +1623,7 @@ public abstract class World implements IBlockAccess { + byte b0 = 32; + + // Spigot start +- if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { ++ if (flag && !org.spigotmc.ActivationRange.checkIfActive(entity)) { + entity.ticksLived++; + entity.inactiveTick(); + } else { diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java index f0d3a19..a1bd1a6 100644 --- a/src/main/java/org/spigotmc/ActivationRange.java diff --git a/pom.xml b/pom.xml index 066f8d889..ee0f11f16 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,10 @@ md_5-releases http://repo.md-5.net/content/repositories/releases/ + + aikar + https://ci.emc.gs/nexus/content/repositories/aikar/ + @@ -48,4 +52,4 @@ https://repo.destroystokyo.com/content/repositories/snapshots/ - \ No newline at end of file +