From c2f872aed351ecceae51068c2f2e60218f733d00 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 30 Mar 2016 01:57:56 -0400 Subject: [PATCH] Add Minimal FastUtil int/long collections. Importing the full library would double the jar size... its way too large. So lets just import the basic int/long based collections to then use to improve performance on these kind of collections. --- ...nimal-fastutil-int-based-collections.patch | 45209 ++++++++++++++++ ...Timings-v2.patch => 0003-Timings-v2.patch} | 0 ...=> 0004-Player-affects-spawning-API.patch} | 6 +- ...hod.patch => 0005-Add-getTPS-method.patch} | 4 +- ...ch => 0006-Add-async-chunk-load-API.patch} | 4 +- ...API.patch => 0007-Entity-Origin-API.patch} | 4 +- ....patch => 0008-Check-Paper-versions.patch} | 4 +- ...=> 0009-Add-PlayerLocaleChangeEvent.patch} | 4 +- ...> 0010-Add-player-view-distance-API.patch} | 6 +- ...patch => 0011-Add-BeaconEffectEvent.patch} | 4 +- ...=> 0012-Add-PlayerInitialSpawnEvent.patch} | 4 +- ...ort-to-tab-completers-vanilla-featu.patch} | 4 +- ...ade-EntityDismountEvent-Cancellable.patch} | 4 +- ...y-disable-plugins-that-fail-to-load.patch} | 4 +- ...ch => 0016-Expose-server-CommandMap.patch} | 6 +- ...ord-chat-API-from-spigot-subclasses.patch} | 8 +- ...0018-Player-Tab-List-and-Title-APIs.patch} | 6 +- ... 0019-Add-exception-reporting-event.patch} | 4 +- ...rverListPingEvent-flagging-as-Async.patch} | 4 +- ...-sendMessage-methods-to-CommandSend.patch} | 6 +- ...orking-with-arrows-stuck-in-living-.patch} | 4 +- ... => 0023-Complete-resource-pack-API.patch} | 6 +- ...=> 0024-Use-ASM-for-event-executors.patch} | 6 +- ... => 0025-Add-a-call-helper-to-Event.patch} | 4 +- ...er-name-to-commands.yml-replacement.patch} | 4 +- ...load-permissions.yml-and-require-co.patch} | 4 +- ...-Custom-replacement-for-eaten-items.patch} | 4 +- ... 0029-Access-items-by-EquipmentSlot.patch} | 4 +- ...ntity-AddTo-RemoveFrom-World-Events.patch} | 4 +- ...t.patch => 0031-EntityPathfindEvent.patch} | 4 +- ...ynchronization-in-MetadataStoreBase.patch} | 4 +- ...-MetadataStoreBase.removeAll-Plugin.patch} | 4 +- 32 files changed, 45278 insertions(+), 69 deletions(-) create mode 100644 Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch rename Spigot-API-Patches/{0002-Timings-v2.patch => 0003-Timings-v2.patch} (100%) rename Spigot-API-Patches/{0003-Player-affects-spawning-API.patch => 0004-Player-affects-spawning-API.patch} (90%) rename Spigot-API-Patches/{0004-Add-getTPS-method.patch => 0005-Add-getTPS-method.patch} (94%) rename Spigot-API-Patches/{0005-Add-async-chunk-load-API.patch => 0006-Add-async-chunk-load-API.patch} (97%) rename Spigot-API-Patches/{0006-Entity-Origin-API.patch => 0007-Entity-Origin-API.patch} (96%) rename Spigot-API-Patches/{0007-Check-Paper-versions.patch => 0008-Check-Paper-versions.patch} (98%) rename Spigot-API-Patches/{0008-Add-PlayerLocaleChangeEvent.patch => 0009-Add-PlayerLocaleChangeEvent.patch} (95%) rename Spigot-API-Patches/{0009-Add-player-view-distance-API.patch => 0010-Add-player-view-distance-API.patch} (89%) rename Spigot-API-Patches/{0010-Add-BeaconEffectEvent.patch => 0011-Add-BeaconEffectEvent.patch} (96%) rename Spigot-API-Patches/{0011-Add-PlayerInitialSpawnEvent.patch => 0012-Add-PlayerInitialSpawnEvent.patch} (95%) rename Spigot-API-Patches/{0012-Add-Location-support-to-tab-completers-vanilla-featu.patch => 0013-Add-Location-support-to-tab-completers-vanilla-featu.patch} (99%) rename Spigot-API-Patches/{0013-Made-EntityDismountEvent-Cancellable.patch => 0014-Made-EntityDismountEvent-Cancellable.patch} (95%) rename Spigot-API-Patches/{0014-Automatically-disable-plugins-that-fail-to-load.patch => 0015-Automatically-disable-plugins-that-fail-to-load.patch} (93%) rename Spigot-API-Patches/{0015-Expose-server-CommandMap.patch => 0016-Expose-server-CommandMap.patch} (95%) rename Spigot-API-Patches/{0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch => 0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch} (95%) rename Spigot-API-Patches/{0017-Player-Tab-List-and-Title-APIs.patch => 0018-Player-Tab-List-and-Title-APIs.patch} (99%) rename Spigot-API-Patches/{0018-Add-exception-reporting-event.patch => 0019-Add-exception-reporting-event.patch} (99%) rename Spigot-API-Patches/{0019-Fix-ServerListPingEvent-flagging-as-Async.patch => 0020-Fix-ServerListPingEvent-flagging-as-Async.patch} (96%) rename Spigot-API-Patches/{0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch => 0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch} (95%) rename Spigot-API-Patches/{0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch => 0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch} (93%) rename Spigot-API-Patches/{0022-Complete-resource-pack-API.patch => 0023-Complete-resource-pack-API.patch} (97%) rename Spigot-API-Patches/{0023-Use-ASM-for-event-executors.patch => 0024-Use-ASM-for-event-executors.patch} (99%) rename Spigot-API-Patches/{0024-Add-a-call-helper-to-Event.patch => 0025-Add-a-call-helper-to-Event.patch} (94%) rename Spigot-API-Patches/{0025-Add-sender-name-to-commands.yml-replacement.patch => 0026-Add-sender-name-to-commands.yml-replacement.patch} (96%) rename Spigot-API-Patches/{0026-Add-command-to-reload-permissions.yml-and-require-co.patch => 0027-Add-command-to-reload-permissions.yml-and-require-co.patch} (98%) rename Spigot-API-Patches/{0027-Custom-replacement-for-eaten-items.patch => 0028-Custom-replacement-for-eaten-items.patch} (95%) rename Spigot-API-Patches/{0028-Access-items-by-EquipmentSlot.patch => 0029-Access-items-by-EquipmentSlot.patch} (93%) rename Spigot-API-Patches/{0029-Entity-AddTo-RemoveFrom-World-Events.patch => 0030-Entity-AddTo-RemoveFrom-World-Events.patch} (97%) rename Spigot-API-Patches/{0030-EntityPathfindEvent.patch => 0031-EntityPathfindEvent.patch} (97%) rename Spigot-API-Patches/{0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch => 0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch} (98%) rename Spigot-API-Patches/{0032-Add-MetadataStoreBase.removeAll-Plugin.patch => 0033-Add-MetadataStoreBase.removeAll-Plugin.patch} (95%) diff --git a/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch b/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch new file mode 100644 index 0000000000..76155c3943 --- /dev/null +++ b/Spigot-API-Patches/0002-Add-minimal-fastutil-int-based-collections.patch @@ -0,0 +1,45209 @@ +From 8856eed99403409f9904fb8315ff4f2e95065239 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Mon, 21 Mar 2016 18:17:14 -0400 +Subject: [PATCH] Add minimal fastutil int based collections + + +diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java +new file mode 100644 +index 0000000..4778cfa +--- /dev/null ++++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java +@@ -0,0 +1,29 @@ ++package it.unimi.dsi.fastutil; ++ ++/* ++ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++/** An abstract class providing basic methods for implementing the {@link IndirectDoublePriorityQueue} interface. ++ * ++ *

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-Timings-v2.patch b/Spigot-API-Patches/0003-Timings-v2.patch similarity index 100% rename from Spigot-API-Patches/0002-Timings-v2.patch rename to Spigot-API-Patches/0003-Timings-v2.patch diff --git a/Spigot-API-Patches/0003-Player-affects-spawning-API.patch b/Spigot-API-Patches/0004-Player-affects-spawning-API.patch similarity index 90% rename from Spigot-API-Patches/0003-Player-affects-spawning-API.patch rename to Spigot-API-Patches/0004-Player-affects-spawning-API.patch index cb73d630e8..babadf82ce 100644 --- a/Spigot-API-Patches/0003-Player-affects-spawning-API.patch +++ b/Spigot-API-Patches/0004-Player-affects-spawning-API.patch @@ -1,11 +1,11 @@ -From 5ae17d42515dab32a03341740fd3b99aeb4c4420 Mon Sep 17 00:00:00 2001 +From e5bf28b61af878aee9b97ab52d6ed6930487362f Mon Sep 17 00:00:00 2001 From: Jedediah Smith Date: Mon, 29 Feb 2016 17:22:34 -0600 Subject: [PATCH] Player affects spawning API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 3242c69..0979f94 100644 +index 19f7ae7..145bb15 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1270,6 +1270,20 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline @@ -30,5 +30,5 @@ index 3242c69..0979f94 100644 public class Spigot extends Entity.Spigot { -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0004-Add-getTPS-method.patch b/Spigot-API-Patches/0005-Add-getTPS-method.patch similarity index 94% rename from Spigot-API-Patches/0004-Add-getTPS-method.patch rename to Spigot-API-Patches/0005-Add-getTPS-method.patch index 901837b19e..cd9252ec25 100644 --- a/Spigot-API-Patches/0004-Add-getTPS-method.patch +++ b/Spigot-API-Patches/0005-Add-getTPS-method.patch @@ -1,4 +1,4 @@ -From c84a859dcf623824d3fa4f45d0fdb00c96f791a3 Mon Sep 17 00:00:00 2001 +From f41ba48d012b47e2ea11fae6e58e595e93ba47e1 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 29 Feb 2016 17:24:57 -0600 Subject: [PATCH] Add getTPS method @@ -42,5 +42,5 @@ index f82cbaf..6e23b0c 100644 * @return the unsafe values instance */ -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0005-Add-async-chunk-load-API.patch b/Spigot-API-Patches/0006-Add-async-chunk-load-API.patch similarity index 97% rename from Spigot-API-Patches/0005-Add-async-chunk-load-API.patch rename to Spigot-API-Patches/0006-Add-async-chunk-load-API.patch index 6175ac1a9a..28f2d800d8 100644 --- a/Spigot-API-Patches/0005-Add-async-chunk-load-API.patch +++ b/Spigot-API-Patches/0006-Add-async-chunk-load-API.patch @@ -1,4 +1,4 @@ -From 185a0dc471a2a1f5c74365f576ef3fecc04077cf Mon Sep 17 00:00:00 2001 +From 410427fe9f7aa75592d7ba4aec7cfc78ae868da7 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 29 Feb 2016 17:43:33 -0600 Subject: [PATCH] Add async chunk load API @@ -88,5 +88,5 @@ index d088c3c..d16facb 100644 * * @param chunk The chunk to check -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0006-Entity-Origin-API.patch b/Spigot-API-Patches/0007-Entity-Origin-API.patch similarity index 96% rename from Spigot-API-Patches/0006-Entity-Origin-API.patch rename to Spigot-API-Patches/0007-Entity-Origin-API.patch index 706216082d..6355ad2394 100644 --- a/Spigot-API-Patches/0006-Entity-Origin-API.patch +++ b/Spigot-API-Patches/0007-Entity-Origin-API.patch @@ -1,4 +1,4 @@ -From fc936348f326dc7f042c1791eb98627a7fa97008 Mon Sep 17 00:00:00 2001 +From 80f0b1f242c4e32979a05cc74f0e482c2fdbc0fa Mon Sep 17 00:00:00 2001 From: Byteflux Date: Mon, 29 Feb 2016 17:50:31 -0600 Subject: [PATCH] Entity Origin API @@ -61,5 +61,5 @@ index 3ce322d..69df487 100644 + public org.bukkit.Location getSourceLoc(); } -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0007-Check-Paper-versions.patch b/Spigot-API-Patches/0008-Check-Paper-versions.patch similarity index 98% rename from Spigot-API-Patches/0007-Check-Paper-versions.patch rename to Spigot-API-Patches/0008-Check-Paper-versions.patch index 91619a8493..121ebfbd95 100644 --- a/Spigot-API-Patches/0007-Check-Paper-versions.patch +++ b/Spigot-API-Patches/0008-Check-Paper-versions.patch @@ -1,4 +1,4 @@ -From 8945fdcb9e256a858154ee2bd510b0be242c9258 Mon Sep 17 00:00:00 2001 +From 1c6c69b96da276f32ff330c25091299c3efd1fbd Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 29 Feb 2016 17:58:01 -0600 Subject: [PATCH] Check Paper versions @@ -139,5 +139,5 @@ index b55abdb..6d32e1d 100644 + // Paper end } -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch b/Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch similarity index 95% rename from Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch rename to Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch index 02614623d6..96dbbb26d1 100644 --- a/Spigot-API-Patches/0008-Add-PlayerLocaleChangeEvent.patch +++ b/Spigot-API-Patches/0009-Add-PlayerLocaleChangeEvent.patch @@ -1,4 +1,4 @@ -From bb0becc6c80fa0996078cc9e7d5bb3e0dea72611 Mon Sep 17 00:00:00 2001 +From 5bbfd17e10b92832b0459da91bb1044c3eb38f17 Mon Sep 17 00:00:00 2001 From: Isaac Moore Date: Mon, 29 Feb 2016 18:02:25 -0600 Subject: [PATCH] Add PlayerLocaleChangeEvent @@ -58,5 +58,5 @@ index 0000000..17afc8c + } +} -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0009-Add-player-view-distance-API.patch b/Spigot-API-Patches/0010-Add-player-view-distance-API.patch similarity index 89% rename from Spigot-API-Patches/0009-Add-player-view-distance-API.patch rename to Spigot-API-Patches/0010-Add-player-view-distance-API.patch index 3027cd6e55..8fa2ba8098 100644 --- a/Spigot-API-Patches/0009-Add-player-view-distance-API.patch +++ b/Spigot-API-Patches/0010-Add-player-view-distance-API.patch @@ -1,11 +1,11 @@ -From a4a5ff9f015a914a3967d0392769a74190945cba Mon Sep 17 00:00:00 2001 +From ddf27421558eedfa849d43c38652e43e6b785145 Mon Sep 17 00:00:00 2001 From: Byteflux Date: Mon, 29 Feb 2016 18:05:37 -0600 Subject: [PATCH] Add player view distance API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 0979f94..1a11c2b 100644 +index 145bb15..66527ce 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1284,6 +1284,20 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline @@ -30,5 +30,5 @@ index 0979f94..1a11c2b 100644 public class Spigot extends Entity.Spigot { -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch b/Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch similarity index 96% rename from Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch rename to Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch index 4de1ba4dd4..0f8bb9975d 100644 --- a/Spigot-API-Patches/0010-Add-BeaconEffectEvent.patch +++ b/Spigot-API-Patches/0011-Add-BeaconEffectEvent.patch @@ -1,4 +1,4 @@ -From dcd1942fd0c3527281f9411bd7c4103ebdf00f1e Mon Sep 17 00:00:00 2001 +From 93d98d9a2a4d8cbef43ca5b9e7fbad4d6cf925a5 Mon Sep 17 00:00:00 2001 From: Byteflux Date: Mon, 29 Feb 2016 18:09:40 -0600 Subject: [PATCH] Add BeaconEffectEvent @@ -92,5 +92,5 @@ index 0000000..6579ae9 + } +} -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch b/Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch similarity index 95% rename from Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch rename to Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch index 5fe29f0678..625d6bd6d5 100644 --- a/Spigot-API-Patches/0011-Add-PlayerInitialSpawnEvent.patch +++ b/Spigot-API-Patches/0012-Add-PlayerInitialSpawnEvent.patch @@ -1,4 +1,4 @@ -From 3eba221a754f0bdf4bc31cc105ed33757d4ab7f0 Mon Sep 17 00:00:00 2001 +From 3dabbf24d9e169631ff0f11df707e0623c4d2cc4 Mon Sep 17 00:00:00 2001 From: Steve Anton Date: Mon, 29 Feb 2016 18:13:58 -0600 Subject: [PATCH] Add PlayerInitialSpawnEvent @@ -55,5 +55,5 @@ index 0000000..d1d6f33 + } +} -- -2.7.1.windows.2 +2.8.0 diff --git a/Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch b/Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch similarity index 99% rename from Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch rename to Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch index b030d32962..7ce83ab327 100644 --- a/Spigot-API-Patches/0012-Add-Location-support-to-tab-completers-vanilla-featu.patch +++ b/Spigot-API-Patches/0013-Add-Location-support-to-tab-completers-vanilla-featu.patch @@ -1,4 +1,4 @@ -From 78cc4ff51183b89e12aa39a47d39bf06497613ea Mon Sep 17 00:00:00 2001 +From 95affa5d23889fc61fbc4a2c37879369754609c3 Mon Sep 17 00:00:00 2001 From: DemonWav Date: Mon, 29 Feb 2016 19:37:41 -0600 Subject: [PATCH] Add Location support to tab completers (vanilla feature @@ -165,5 +165,5 @@ index 6d61e3a..85b10e5 100644 + // Paper end } -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch b/Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch similarity index 95% rename from Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch rename to Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch index 16277b76f3..9efcf8a044 100644 --- a/Spigot-API-Patches/0013-Made-EntityDismountEvent-Cancellable.patch +++ b/Spigot-API-Patches/0014-Made-EntityDismountEvent-Cancellable.patch @@ -1,4 +1,4 @@ -From ae556b9d833294cf0e1f865b6851447a11cdcda5 Mon Sep 17 00:00:00 2001 +From 72bedfe51658b0464677c52347151e5525b85307 Mon Sep 17 00:00:00 2001 From: Nik Gil Date: Mon, 29 Feb 2016 19:42:10 -0600 Subject: [PATCH] Made EntityDismountEvent Cancellable @@ -43,5 +43,5 @@ index 24d4942..ce989bb 100644 + // Paper end } -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch b/Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch similarity index 93% rename from Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch rename to Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch index 78feefc3f0..41650100af 100644 --- a/Spigot-API-Patches/0014-Automatically-disable-plugins-that-fail-to-load.patch +++ b/Spigot-API-Patches/0015-Automatically-disable-plugins-that-fail-to-load.patch @@ -1,4 +1,4 @@ -From 9003dd80621ac325f76aab4af72047c9da57f691 Mon Sep 17 00:00:00 2001 +From 9b9ccba2ed63a98b146b388fd175e9d350e05dfd Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 29 Feb 2016 19:45:21 -0600 Subject: [PATCH] Automatically disable plugins that fail to load @@ -20,5 +20,5 @@ index 4983ea8..93a43dd 100644 // Perhaps abort here, rather than continue going, but as it stands, -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch b/Spigot-API-Patches/0016-Expose-server-CommandMap.patch similarity index 95% rename from Spigot-API-Patches/0015-Expose-server-CommandMap.patch rename to Spigot-API-Patches/0016-Expose-server-CommandMap.patch index 1e2c2b8a8e..1c8df16482 100644 --- a/Spigot-API-Patches/0015-Expose-server-CommandMap.patch +++ b/Spigot-API-Patches/0016-Expose-server-CommandMap.patch @@ -1,4 +1,4 @@ -From 7c9892de7be9a27ba1014d2ee6202c70230b114d Mon Sep 17 00:00:00 2001 +From e56e4b8d652e65f05ed1102a811ec81508f7af4a Mon Sep 17 00:00:00 2001 From: kashike Date: Mon, 29 Feb 2016 19:48:59 -0600 Subject: [PATCH] Expose server CommandMap @@ -39,7 +39,7 @@ index 8d602a3..b6a0b40 100644 { return server.spigot(); diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 86fe389..9ee3815 100644 +index 6e23b0c..a1ce356 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -17,10 +17,7 @@ import org.bukkit.boss.BarColor; @@ -70,5 +70,5 @@ index 86fe389..9ee3815 100644 * @see UnsafeValues * @return the unsafe values instance -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch b/Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch similarity index 95% rename from Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch rename to Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch index 254b7bd7a0..24a1137e87 100644 --- a/Spigot-API-Patches/0016-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch +++ b/Spigot-API-Patches/0017-Graduate-bungeecord-chat-API-from-spigot-subclasses.patch @@ -1,4 +1,4 @@ -From 47ecb6bf0557814cd48f9b732e1bd5bee223f923 Mon Sep 17 00:00:00 2001 +From ab8308a04ebe3b5e2ff0a93c1527b335a3d5f3a7 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 29 Feb 2016 19:54:32 -0600 Subject: [PATCH] Graduate bungeecord chat API from spigot subclasses @@ -36,7 +36,7 @@ index b6a0b40..f93ca2e 100644 * Gets the name of the update folder. The update folder is used to safely * update plugins at the right moment on a plugin load. diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java -index 9ee3815..77d4f34 100644 +index a1ce356..91bde81 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -238,6 +238,22 @@ public interface Server extends PluginMessageRecipient { @@ -63,7 +63,7 @@ index 9ee3815..77d4f34 100644 * Gets the name of the update folder. The update folder is used to safely * update plugins at the right moment on a plugin load. diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 855bde5..024b8dd 100644 +index 66527ce..edf35f5 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -331,6 +331,22 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline @@ -90,5 +90,5 @@ index 855bde5..024b8dd 100644 * Forces an update of the player's entire inventory. * -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch b/Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch similarity index 99% rename from Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch rename to Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch index 3d592a99cb..464543e540 100644 --- a/Spigot-API-Patches/0017-Player-Tab-List-and-Title-APIs.patch +++ b/Spigot-API-Patches/0018-Player-Tab-List-and-Title-APIs.patch @@ -1,4 +1,4 @@ -From 084b100716809ddb5c563ed03318c2cb010f7382 Mon Sep 17 00:00:00 2001 +From a0fabc2ea5c62e58d9c7caef415eabe3de6c9fb8 Mon Sep 17 00:00:00 2001 From: Techcable Date: Mon, 29 Feb 2016 20:02:40 -0600 Subject: [PATCH] Player Tab List and Title APIs @@ -369,7 +369,7 @@ index 0000000..e1ecd44 + } +} diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 024b8dd..50a6a41 100644 +index edf35f5..5326ea6 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -2,6 +2,7 @@ package org.bukkit.entity; @@ -507,5 +507,5 @@ index 024b8dd..50a6a41 100644 -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch b/Spigot-API-Patches/0019-Add-exception-reporting-event.patch similarity index 99% rename from Spigot-API-Patches/0018-Add-exception-reporting-event.patch rename to Spigot-API-Patches/0019-Add-exception-reporting-event.patch index ae12c5b915..ff7f9336ec 100644 --- a/Spigot-API-Patches/0018-Add-exception-reporting-event.patch +++ b/Spigot-API-Patches/0019-Add-exception-reporting-event.patch @@ -1,4 +1,4 @@ -From d6d60f8002718e1a350932f6d62cd10babcb4c53 Mon Sep 17 00:00:00 2001 +From dec653a0fcd117f48e13a63d763fd7387d1d58a0 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 29 Feb 2016 20:24:35 -0600 Subject: [PATCH] Add exception reporting event @@ -587,5 +587,5 @@ index 1325b03..49f5872 100644 } } -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch b/Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch similarity index 96% rename from Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch rename to Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch index 2d47507f74..468fa45d52 100644 --- a/Spigot-API-Patches/0019-Fix-ServerListPingEvent-flagging-as-Async.patch +++ b/Spigot-API-Patches/0020-Fix-ServerListPingEvent-flagging-as-Async.patch @@ -1,4 +1,4 @@ -From c872380e8a9e221324e69639a39bffb18fc8f883 Mon Sep 17 00:00:00 2001 +From 40cea5b463eada81ab6b30330ed739615a97c9bd Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 29 Feb 2016 20:26:39 -0600 Subject: [PATCH] Fix ServerListPingEvent flagging as Async @@ -50,5 +50,5 @@ index 343f238..3c38d85 100644 this.address = address; this.motd = motd; -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch b/Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch similarity index 95% rename from Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch rename to Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch index 68e5a6d74f..b5903635ef 100644 --- a/Spigot-API-Patches/0020-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch +++ b/Spigot-API-Patches/0021-Add-BaseComponent-sendMessage-methods-to-CommandSend.patch @@ -1,4 +1,4 @@ -From c86b4710176897c1c3cffa381cc212ff53c0fe4a Mon Sep 17 00:00:00 2001 +From 2f744e6d6116fd4debbba556368e44db6d1b9090 Mon Sep 17 00:00:00 2001 From: kashike Date: Tue, 8 Mar 2016 13:05:59 -0800 Subject: [PATCH] Add BaseComponent sendMessage methods to CommandSender @@ -40,7 +40,7 @@ index 148756b..4ad0028 100644 + // Paper end } diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index 8124c71..b9c9af0 100644 +index 5326ea6..2951b98 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -338,6 +338,7 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline @@ -60,5 +60,5 @@ index 8124c71..b9c9af0 100644 /** -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch b/Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch similarity index 93% rename from Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch rename to Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch index 1ae4fdf758..3313ad4508 100644 --- a/Spigot-API-Patches/0021-Add-methods-for-working-with-arrows-stuck-in-living-.patch +++ b/Spigot-API-Patches/0022-Add-methods-for-working-with-arrows-stuck-in-living-.patch @@ -1,4 +1,4 @@ -From ed0f87d97dc3b1e85e2ef56ba8d6ec1e871df32d Mon Sep 17 00:00:00 2001 +From 578d1f92b19a427d2deb9ded55c699ea9fdbdec4 Mon Sep 17 00:00:00 2001 From: mrapple Date: Sun, 25 Nov 2012 13:47:27 -0600 Subject: [PATCH] Add methods for working with arrows stuck in living entities @@ -29,5 +29,5 @@ index 22de9f7..570da41 100644 + // Paper end } -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch b/Spigot-API-Patches/0023-Complete-resource-pack-API.patch similarity index 97% rename from Spigot-API-Patches/0022-Complete-resource-pack-API.patch rename to Spigot-API-Patches/0023-Complete-resource-pack-API.patch index 0eef6f3aba..8eed7d6b10 100644 --- a/Spigot-API-Patches/0022-Complete-resource-pack-API.patch +++ b/Spigot-API-Patches/0023-Complete-resource-pack-API.patch @@ -1,11 +1,11 @@ -From fa6a25250e75d5ec7ded2fc985067a64e71e6b0f Mon Sep 17 00:00:00 2001 +From 7b4059b9b56f49f1a227fb39b1ea909245a1203d Mon Sep 17 00:00:00 2001 From: Jedediah Smith Date: Sat, 4 Apr 2015 22:59:54 -0400 Subject: [PATCH] Complete resource pack API diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java -index b9c9af0..b7496a3 100644 +index 2951b98..d7c8069 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1099,7 +1099,9 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline @@ -110,5 +110,5 @@ index 4c49801..4c83851 100644 * Gets the status of this pack. * -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch similarity index 99% rename from Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch rename to Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch index 338c2ae3d4..01ce28e4af 100644 --- a/Spigot-API-Patches/0023-Use-ASM-for-event-executors.patch +++ b/Spigot-API-Patches/0024-Use-ASM-for-event-executors.patch @@ -1,4 +1,4 @@ -From c1dc52ffb0997b633a552eb4fc6341de01a50e40 Mon Sep 17 00:00:00 2001 +From e5e95709d29d23cb34387060e95de1aad352e432 Mon Sep 17 00:00:00 2001 From: Techcable Date: Thu, 3 Mar 2016 13:20:33 -0700 Subject: [PATCH] Use ASM for event executors. @@ -6,7 +6,7 @@ Subject: [PATCH] Use ASM for event executors. Uses method handles for private or static methods. diff --git a/pom.xml b/pom.xml -index 0b615b4..1ad108e 100644 +index d3a877a..92a729b 100644 --- a/pom.xml +++ b/pom.xml @@ -112,6 +112,12 @@ @@ -395,5 +395,5 @@ index 93a43dd..7229b25 100644 eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); } else { -- -2.7.2 +2.8.0 diff --git a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch b/Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch similarity index 94% rename from Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch rename to Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch index f6683f7025..0419c1611d 100644 --- a/Spigot-API-Patches/0024-Add-a-call-helper-to-Event.patch +++ b/Spigot-API-Patches/0025-Add-a-call-helper-to-Event.patch @@ -1,4 +1,4 @@ -From 82df1be4b32c98bc98852d11792b42808db38322 Mon Sep 17 00:00:00 2001 +From 81c991a2a0e0f1f58a73b49bb276ab52884d433d Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 19 May 2013 20:36:58 -0400 Subject: [PATCH] Add a call helper to Event @@ -40,5 +40,5 @@ index 6677e1b..eaf6c49 100644 * Convenience method for providing a user-friendly identifier. By * default, it is the event's class's {@linkplain Class#getSimpleName() -- -2.7.3 +2.8.0 diff --git a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch b/Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch similarity index 96% rename from Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch rename to Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch index f81e32ca77..26a3c3334f 100644 --- a/Spigot-API-Patches/0025-Add-sender-name-to-commands.yml-replacement.patch +++ b/Spigot-API-Patches/0026-Add-sender-name-to-commands.yml-replacement.patch @@ -1,4 +1,4 @@ -From 69a33cc93b8fdb90057a7cb3a82fddfe61074033 Mon Sep 17 00:00:00 2001 +From 21d5ec9b192521a3502ad03fdc32d217651ab129 Mon Sep 17 00:00:00 2001 From: Aikar Date: Wed, 22 Jul 2015 18:50:41 -0400 Subject: [PATCH] Add sender name to commands.yml replacement @@ -41,5 +41,5 @@ index f89ad07..a3e9c63 100644 while (index != -1) { int start = index; -- -2.7.3 +2.8.0 diff --git a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch b/Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch similarity index 98% rename from Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch rename to Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch index a428a02ef5..6a9823c7f0 100644 --- a/Spigot-API-Patches/0026-Add-command-to-reload-permissions.yml-and-require-co.patch +++ b/Spigot-API-Patches/0027-Add-command-to-reload-permissions.yml-and-require-co.patch @@ -1,4 +1,4 @@ -From 208b1904b32400b1745e6c89be57fded2d285a60 Mon Sep 17 00:00:00 2001 +From bd8ce76652697575ba15e5efec4710cf0dcd2bba Mon Sep 17 00:00:00 2001 From: William Date: Fri, 18 Mar 2016 03:28:07 -0400 Subject: [PATCH] Add command to reload permissions.yml and require confirm to @@ -102,5 +102,5 @@ index 49f5872..e988a7c 100644 + } -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch b/Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch similarity index 95% rename from Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch rename to Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch index 9f76655eae..7f275a14aa 100644 --- a/Spigot-API-Patches/0027-Custom-replacement-for-eaten-items.patch +++ b/Spigot-API-Patches/0028-Custom-replacement-for-eaten-items.patch @@ -1,4 +1,4 @@ -From 11d6fcf537a9f03b483874c2c2dee87a71fe19ca Mon Sep 17 00:00:00 2001 +From 9ffd06f684daada133fc1b90cc983c8598a6e328 Mon Sep 17 00:00:00 2001 From: Jedediah Smith Date: Sun, 21 Jun 2015 15:05:21 -0400 Subject: [PATCH] Custom replacement for eaten items @@ -42,5 +42,5 @@ index 8ab76b1..42aad88 100644 return this.isCancelled; } -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch b/Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch similarity index 93% rename from Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch rename to Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch index 50ce81d309..79eb545240 100644 --- a/Spigot-API-Patches/0028-Access-items-by-EquipmentSlot.patch +++ b/Spigot-API-Patches/0029-Access-items-by-EquipmentSlot.patch @@ -1,4 +1,4 @@ -From df17741c376cfdac8301e64a9dc9a956e75ae5f1 Mon Sep 17 00:00:00 2001 +From 0024ceed3f1fac5330f4bafd0054f54229489089 Mon Sep 17 00:00:00 2001 From: Jedediah Smith Date: Sun, 20 Mar 2016 06:44:49 -0400 Subject: [PATCH] Access items by EquipmentSlot @@ -32,5 +32,5 @@ index 557cc04..799f150 100644 + // Paper end } -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch b/Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch similarity index 97% rename from Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch rename to Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch index 7bc9059f00..5120a0ad71 100644 --- a/Spigot-API-Patches/0029-Entity-AddTo-RemoveFrom-World-Events.patch +++ b/Spigot-API-Patches/0030-Entity-AddTo-RemoveFrom-World-Events.patch @@ -1,4 +1,4 @@ -From 6fbe0184aa41dd325adc6415b01dda65b1b97c35 Mon Sep 17 00:00:00 2001 +From d32bff844b27d2b2e5827728d21411630c15d25e Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 28 Mar 2016 20:26:34 -0400 Subject: [PATCH] Entity AddTo/RemoveFrom World Events @@ -88,5 +88,5 @@ index 0000000..9b522ce + } +} -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0030-EntityPathfindEvent.patch b/Spigot-API-Patches/0031-EntityPathfindEvent.patch similarity index 97% rename from Spigot-API-Patches/0030-EntityPathfindEvent.patch rename to Spigot-API-Patches/0031-EntityPathfindEvent.patch index 1b037fb453..9e46fdede4 100644 --- a/Spigot-API-Patches/0030-EntityPathfindEvent.patch +++ b/Spigot-API-Patches/0031-EntityPathfindEvent.patch @@ -1,4 +1,4 @@ -From 973cff5bb740f213b5a90297c9cd132e4a57d8e4 Mon Sep 17 00:00:00 2001 +From 0cbfd3f956fe731e9a2c1e0838afd8cb577e338b Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 28 Mar 2016 21:15:34 -0400 Subject: [PATCH] EntityPathfindEvent @@ -87,5 +87,5 @@ index 0000000..21cab26 + } +} -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch b/Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch similarity index 98% rename from Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch rename to Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch index f4c34be9d7..c30f4d4b5c 100644 --- a/Spigot-API-Patches/0031-Reduce-thread-synchronization-in-MetadataStoreBase.patch +++ b/Spigot-API-Patches/0032-Reduce-thread-synchronization-in-MetadataStoreBase.patch @@ -1,4 +1,4 @@ -From d8fc6b74a4f590473b3abad8958d0e929df6074f Mon Sep 17 00:00:00 2001 +From dd1173b521819609b5a9625b4da4a464ef403db7 Mon Sep 17 00:00:00 2001 From: crast Date: Sat, 1 Jun 2013 13:52:30 -0600 Subject: [PATCH] Reduce thread synchronization in MetadataStoreBase @@ -101,5 +101,5 @@ index 093c144..64c0f0a 100644 for (Map values : metadataMap.values()) { if (values.containsKey(owningPlugin)) { -- -2.7.4 +2.8.0 diff --git a/Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch b/Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch similarity index 95% rename from Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch rename to Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch index 90d4b4f811..4d229d2ce5 100644 --- a/Spigot-API-Patches/0032-Add-MetadataStoreBase.removeAll-Plugin.patch +++ b/Spigot-API-Patches/0033-Add-MetadataStoreBase.removeAll-Plugin.patch @@ -1,4 +1,4 @@ -From 9bfe42cfc7f02966926c3dccc68b7dc85e3c25cc Mon Sep 17 00:00:00 2001 +From 61a2f66cc4b6f90f0488d5f4f7df76153ddbbaf9 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 16 Jul 2013 21:26:50 -0400 Subject: [PATCH] Add MetadataStoreBase.removeAll(Plugin) @@ -37,5 +37,5 @@ index 64c0f0a..6da6abd 100644 * unique data from the subject with a metadataKey. *

-- -2.7.4 +2.8.0