f051ea2ab3
For DataWatcher, swap out plain Integer key HashMap for a Int2ObjectOpenHashMap For ChunkProviderServer, swap out CB's custom LongHashMap with Long2ObjectOpenHashMap These collections are super fast as seen http://java-performance.info/hashmap-overview-jdk-fastutil-goldman-sachs-hppc-koloboke-trove-january-2015/
45211 lines
1.8 MiB
45211 lines
1.8 MiB
From bc17a29787a7d9c927d9812b74db623b9ca066b2 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Mon, 21 Mar 2016 18:17:14 -0400
|
|
Subject: [PATCH] Add minimal fastutil int/long based collections
|
|
|
|
Importing entire FastUtil library would be massive. Just import minimal useful ones
|
|
we might actually use.
|
|
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..4778cfa
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
|
|
@@ -0,0 +1,29 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link IndirectDoublePriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #secondaryLast()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractIndirectDoublePriorityQueue<K> extends AbstractIndirectPriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
|
|
+
|
|
+ public int secondaryLast() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..7138801
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
|
|
@@ -0,0 +1,41 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link IndirectPriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #changed(int)}, {@link #allChanged()}, {@link #remove(int)} and {@link #last()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
|
|
+
|
|
+ public int last() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public void changed() { changed( first() ); }
|
|
+
|
|
+ public void changed( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public void allChanged() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean remove( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean contains( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean isEmpty() { return size() == 0; }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..7e819f3
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
|
|
@@ -0,0 +1,35 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link PriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #changed()} and {@link #last()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractPriorityQueue<K> implements PriorityQueue<K> {
|
|
+
|
|
+ public void changed() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public K last() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean isEmpty() { return size() == 0; }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
|
|
new file mode 100644
|
|
index 0000000..faf3e7c
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
|
|
@@ -0,0 +1,41 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link Stack} interface.
|
|
+ *
|
|
+ * <P>This class just defines {@link Stack#top()} as {@link Stack#peek(int) peek(0)}, and
|
|
+ * {@link Stack#peek(int)} as throwing an {@link UnsupportedOperationException}.
|
|
+ *
|
|
+ * Subclasses of this class may choose to implement just {@link Stack#push(Object)},
|
|
+ * {@link Stack#pop()} and {@link Stack#isEmpty()}, or (but this is not
|
|
+ * required) go farther and implement {@link Stack#top()}, or even {@link
|
|
+ * Stack#peek(int)}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractStack<K> implements Stack<K> {
|
|
+
|
|
+ public K top() {
|
|
+ return peek( 0 );
|
|
+ }
|
|
+
|
|
+ public K peek( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Arrays.java b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
|
|
new file mode 100644
|
|
index 0000000..e57cc0a
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
|
|
@@ -0,0 +1,437 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import it.unimi.dsi.fastutil.ints.IntComparator;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with arrays.
|
|
+ *
|
|
+ * <p>In addition to commodity methods, this class contains {@link Swapper}-based implementations
|
|
+ * of {@linkplain #quickSort(int, int, IntComparator, Swapper) quicksort} and of
|
|
+ * a stable, in-place {@linkplain #mergeSort(int, int, IntComparator, Swapper) mergesort}. These
|
|
+ * generic sorting methods can be used to sort any kind of list, but they find their natural
|
|
+ * usage, for instance, in sorting arrays in parallel.
|
|
+ *
|
|
+ * @see Arrays
|
|
+ */
|
|
+
|
|
+public class Arrays {
|
|
+
|
|
+ private Arrays() {}
|
|
+
|
|
+ /** This is a safe value used by {@link ArrayList} (as of Java 7) to avoid
|
|
+ * throwing {@link OutOfMemoryError} on some JVMs. We adopt the same value. */
|
|
+ public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
|
+
|
|
+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array of given length.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param arrayLength an array length.
|
|
+ * @param from a start index (inclusive).
|
|
+ * @param to an end index (inclusive).
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than <code>arrayLength</code> or negative.
|
|
+ */
|
|
+ public static void ensureFromTo( final int arrayLength, final int from, final int to ) {
|
|
+ if ( from < 0 ) throw new ArrayIndexOutOfBoundsException( "Start index (" + from + ") is negative" );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( to > arrayLength ) throw new ArrayIndexOutOfBoundsException( "End index (" + to + ") is greater than array length (" + arrayLength + ")" );
|
|
+ }
|
|
+
|
|
+ /** Ensures that a range given by an offset and a length fits an array of given length.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param arrayLength an array length.
|
|
+ * @param offset a start index for the fragment
|
|
+ * @param length a length (the number of elements in the fragment).
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than <code>arrayLength</code>.
|
|
+ */
|
|
+ public static void ensureOffsetLength( final int arrayLength, final int offset, final int length ) {
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( length < 0 ) throw new IllegalArgumentException( "Length (" + length + ") is negative" );
|
|
+ if ( offset + length > arrayLength ) throw new ArrayIndexOutOfBoundsException( "Last index (" + ( offset + length ) + ") is greater than array length (" + arrayLength + ")" );
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Transforms two consecutive sorted ranges into a single sorted range. The initial ranges are
|
|
+ * <code>[first..middle)</code> and <code>[middle..last)</code>, and the resulting range is
|
|
+ * <code>[first..last)</code>. Elements in the first input range will precede equal elements in
|
|
+ * the second.
|
|
+ */
|
|
+ private static void inPlaceMerge( final int from, int mid, final int to, final IntComparator comp, final Swapper swapper ) {
|
|
+ if ( from >= mid || mid >= to ) return;
|
|
+ if ( to - from == 2 ) {
|
|
+ if ( comp.compare( mid, from ) < 0 ) swapper.swap( from, mid );
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int firstCut;
|
|
+ int secondCut;
|
|
+
|
|
+ if ( mid - from > to - mid ) {
|
|
+ firstCut = from + ( mid - from ) / 2;
|
|
+ secondCut = lowerBound( mid, to, firstCut, comp );
|
|
+ }
|
|
+ else {
|
|
+ secondCut = mid + ( to - mid ) / 2;
|
|
+ firstCut = upperBound( from, mid, secondCut, comp );
|
|
+ }
|
|
+
|
|
+ int first2 = firstCut;
|
|
+ int middle2 = mid;
|
|
+ int last2 = secondCut;
|
|
+ if ( middle2 != first2 && middle2 != last2 ) {
|
|
+ int first1 = first2;
|
|
+ int last1 = middle2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ first1 = middle2;
|
|
+ last1 = last2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ first1 = first2;
|
|
+ last1 = last2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ }
|
|
+
|
|
+ mid = firstCut + ( secondCut - mid );
|
|
+ inPlaceMerge( from, firstCut, mid, comp, swapper );
|
|
+ inPlaceMerge( mid, secondCut, to, comp, swapper );
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Performs a binary search on an already-sorted range: finds the first position where an
|
|
+ * element can be inserted without violating the ordering. Sorting is by a user-supplied
|
|
+ * comparison function.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be included in the binary search.
|
|
+ * @param to the index of the last element (exclusive) to be included in the binary search.
|
|
+ * @param pos the position of the element to be searched for.
|
|
+ * @param comp the comparison function.
|
|
+ * @return the largest index i such that, for every j in the range <code>[first..i)</code>,
|
|
+ * <code>comp.compare(j, pos)</code> is <code>true</code>.
|
|
+ */
|
|
+ private static int lowerBound( int from, final int to, final int pos, final IntComparator comp ) {
|
|
+ // if (comp==null) throw new NullPointerException();
|
|
+ int len = to - from;
|
|
+ while ( len > 0 ) {
|
|
+ int half = len / 2;
|
|
+ int middle = from + half;
|
|
+ if ( comp.compare( middle, pos ) < 0 ) {
|
|
+ from = middle + 1;
|
|
+ len -= half + 1;
|
|
+ }
|
|
+ else {
|
|
+ len = half;
|
|
+ }
|
|
+ }
|
|
+ return from;
|
|
+ }
|
|
+
|
|
+
|
|
+ /**
|
|
+ * Performs a binary search on an already sorted range: finds the last position where an element
|
|
+ * can be inserted without violating the ordering. Sorting is by a user-supplied comparison
|
|
+ * function.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be included in the binary search.
|
|
+ * @param to the index of the last element (exclusive) to be included in the binary search.
|
|
+ * @param pos the position of the element to be searched for.
|
|
+ * @param comp the comparison function.
|
|
+ * @return The largest index i such that, for every j in the range <code>[first..i)</code>,
|
|
+ * <code>comp.compare(pos, j)</code> is <code>false</code>.
|
|
+ */
|
|
+ private static int upperBound( int from, final int mid, final int pos, final IntComparator comp ) {
|
|
+ // if (comp==null) throw new NullPointerException();
|
|
+ int len = mid - from;
|
|
+ while ( len > 0 ) {
|
|
+ int half = len / 2;
|
|
+ int middle = from + half;
|
|
+ if ( comp.compare( pos, middle ) < 0 ) {
|
|
+ len = half;
|
|
+ }
|
|
+ else {
|
|
+ from = middle + 1;
|
|
+ len -= half + 1;
|
|
+ }
|
|
+ }
|
|
+ return from;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the index of the median of the three indexed chars.
|
|
+ */
|
|
+ private static int med3( final int a, final int b, final int c, final IntComparator comp ) {
|
|
+ int ab = comp.compare( a, b );
|
|
+ int ac = comp.compare( a, c );
|
|
+ int bc = comp.compare( b, c );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static final int MERGESORT_NO_REC = 16;
|
|
+
|
|
+ /** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. The sorting algorithm is an in-place mergesort that is significantly slower than a
|
|
+ * standard mergesort, as its running time is <i>O</i>(<var>n</var> (log <var>n</var>)<sup>2</sup>), but it does not allocate additional memory; as a result, it can be
|
|
+ * used as a generic sorting algorithm.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param c the comparator to determine the order of the generic data (arguments are positions).
|
|
+ * @param swapper an object that knows how to swap the elements at any two positions.
|
|
+ */
|
|
+ public static void mergeSort( final int from, final int to, final IntComparator c, final Swapper swapper ) {
|
|
+ /*
|
|
+ * We retain the same method signature as quickSort. Given only a comparator and swapper we
|
|
+ * do not know how to copy and move elements from/to temporary arrays. Hence, in contrast to
|
|
+ * the JDK mergesorts this is an "in-place" mergesort, i.e. does not allocate any temporary
|
|
+ * arrays. A non-inplace mergesort would perhaps be faster in most cases, but would require
|
|
+ * non-intuitive delegate objects...
|
|
+ */
|
|
+ final int length = to - from;
|
|
+
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( length < MERGESORT_NO_REC ) {
|
|
+ for ( int i = from; i < to; i++ ) {
|
|
+ for ( int j = i; j > from && ( c.compare( j - 1, j ) > 0 ); j-- ) {
|
|
+ swapper.swap( j, j - 1 );
|
|
+ }
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Recursively sort halves
|
|
+ int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( from, mid, c, swapper );
|
|
+ mergeSort( mid, to, c, swapper );
|
|
+
|
|
+ // If list is already sorted, nothing left to do. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( c.compare( mid - 1, mid ) <= 0 ) return;
|
|
+
|
|
+ // Merge sorted halves
|
|
+ inPlaceMerge( from, mid, to, c, swapper );
|
|
+ }
|
|
+
|
|
+ /** Swaps two sequences of elements using a provided swapper.
|
|
+ *
|
|
+ * @param swapper the swapper.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ * @param n the number of elements to exchange starting at {@code a} and {@code b}.
|
|
+ */
|
|
+ protected static void swap( final Swapper swapper, int a, int b, final int n ) {
|
|
+ for ( int i = 0; i < n; i++, a++, b++ ) swapper.swap( a, b );
|
|
+ }
|
|
+
|
|
+ private static final int QUICKSORT_NO_REC = 16;
|
|
+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
|
|
+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
|
|
+
|
|
+ protected static class ForkJoinGenericQuickSort extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final IntComparator comp;
|
|
+ private final Swapper swapper;
|
|
+
|
|
+ public ForkJoinGenericQuickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.comp = comp;
|
|
+ this.swapper = swapper;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected void compute() {
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( from, to, comp, swapper );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( l, l + s, l + 2 * s, comp );
|
|
+ m = med3( m - s, m, m + s, comp );
|
|
+ n = med3( n - 2 * s, n - s, n, comp );
|
|
+ m = med3( l, m, n, comp );
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( ( comparison = comp.compare( b, m ) ) <= 0 ) ) {
|
|
+ if ( comparison == 0 ) {
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( a == m ) m = b;
|
|
+ else if ( b == m ) m = a;
|
|
+ swapper.swap( a++, b );
|
|
+ }
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( ( comparison = comp.compare( c, m ) ) >= 0 ) ) {
|
|
+ if ( comparison == 0 ) {
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( c == m ) m = d;
|
|
+ else if ( d == m ) m = c;
|
|
+ swapper.swap( c, d-- );
|
|
+ }
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( b == m ) m = d;
|
|
+ else if ( c == m ) m = c;
|
|
+ swapper.swap( b++, c-- );
|
|
+ }
|
|
+
|
|
+ // Swap partition elements back to middle
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( swapper, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( swapper, b, to - s, s );
|
|
+
|
|
+ // Recursively sort non-partition-elements
|
|
+ int t;
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinGenericQuickSort( from, from + s, comp, swapper ), new ForkJoinGenericQuickSort( to - t, to, comp, swapper ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinGenericQuickSort( from, from + s, comp, swapper ) );
|
|
+ else invokeAll( new ForkJoinGenericQuickSort( to - t, to, comp, swapper ) );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the order of the generic data.
|
|
+ * @param swapper an object that knows how to swap the elements at any two positions.
|
|
+ *
|
|
+ */
|
|
+ public static void parallelQuickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinGenericQuickSort( from, to, comp, swapper ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
|
|
+ * comparator using parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the order of the generic data.
|
|
+ * @param swapper an object that knows how to swap the elements at any two positions.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final int from, final int to, final IntComparator comp, final Swapper swapper ) {
|
|
+ final int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ for ( int i = from; i < to; i++ )
|
|
+ for ( int j = i; j > from && ( comp.compare( j - 1, j ) > 0 ); j-- ) {
|
|
+ swapper.swap( j, j - 1 );
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2; // Small arrays, middle element
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( l, l + s, l + 2 * s, comp );
|
|
+ m = med3( m - s, m, m + s, comp );
|
|
+ n = med3( n - 2 * s, n - s, n, comp );
|
|
+ }
|
|
+ m = med3( l, m, n, comp ); // Mid-size, med of 3
|
|
+ // int v = x[m];
|
|
+
|
|
+ int a = from;
|
|
+ int b = a;
|
|
+ int c = to - 1;
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( ( comparison = comp.compare( b, m ) ) <= 0 ) ) {
|
|
+ if ( comparison == 0 ) {
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( a == m ) m = b;
|
|
+ else if ( b == m ) m = a;
|
|
+ swapper.swap( a++, b );
|
|
+ }
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( ( comparison = comp.compare( c, m ) ) >= 0 ) ) {
|
|
+ if ( comparison == 0 ) {
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( c == m ) m = d;
|
|
+ else if ( d == m ) m = c;
|
|
+ swapper.swap( c, d-- );
|
|
+ }
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ // Fix reference to pivot if necessary
|
|
+ if ( b == m ) m = d;
|
|
+ else if ( c == m ) m = c;
|
|
+ swapper.swap( b++, c-- );
|
|
+ }
|
|
+
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( swapper, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( swapper, b, to - s, s );
|
|
+
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( from, from + s, comp, swapper );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( to - s, to, comp, swapper );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..526d78e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
|
|
@@ -0,0 +1,55 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+
|
|
+/** A bidirectional {@link Iterator}.
|
|
+ *
|
|
+ * <P>This kind of iterator is essentially a {@link ListIterator} that
|
|
+ * does not support {@link ListIterator#previousIndex()} and {@link
|
|
+ * ListIterator#nextIndex()}. It is useful for those maps that can easily
|
|
+ * provide bidirectional iteration, but provide no index.
|
|
+ *
|
|
+ * <P>Note that iterators returned by <code>fastutil</code> classes are more
|
|
+ * specific, and support skipping. This class serves the purpose of organising
|
|
+ * in a cleaner way the relationships between various iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ * @see ListIterator
|
|
+ */
|
|
+
|
|
+public interface BidirectionalIterator<K> extends Iterator<K> {
|
|
+
|
|
+ /** Returns the previous element from the collection.
|
|
+ *
|
|
+ * @return the previous element from the collection.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+
|
|
+ K previous();
|
|
+
|
|
+ /** Returns whether there is a previous element.
|
|
+ *
|
|
+ * @return whether there is a previous element.
|
|
+ * @see java.util.ListIterator#hasPrevious()
|
|
+ */
|
|
+
|
|
+ boolean hasPrevious();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
|
|
new file mode 100644
|
|
index 0000000..8f891db
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
|
|
@@ -0,0 +1,32 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** An object that can swap elements whose positions is specified by longs.
|
|
+ *
|
|
+ * @see BigArrays#quickSort(long, long, it.unimi.dsi.fastutil.longs.LongComparator, BigSwapper)
|
|
+ */
|
|
+
|
|
+public interface BigSwapper {
|
|
+ /** Swaps the data at the given positions.
|
|
+ *
|
|
+ * @param a the first position to swap.
|
|
+ * @param b the second position to swap.
|
|
+ */
|
|
+ void swap( long a, long b );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Function.java b/src/main/java/it/unimi/dsi/fastutil/Function.java
|
|
new file mode 100644
|
|
index 0000000..03bb61b
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Function.java
|
|
@@ -0,0 +1,101 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** A function mapping keys into values.
|
|
+ *
|
|
+ * <p>Instances of this class represent functions: the main difference with {@link java.util.Map}
|
|
+ * is that functions do not in principle allow enumeration of their domain or range. The need for
|
|
+ * this interface lies in the existence of several highly optimized implementations of
|
|
+ * functions (e.g., minimal perfect hashes) which do not actually store their domain or range explicitly.
|
|
+ * In case the domain is known, {@link #containsKey(Object)} can be used to perform membership queries.
|
|
+ *
|
|
+ * <p>The choice of naming all methods exactly as in {@link java.util.Map} makes it possible
|
|
+ * for all type-specific maps to extend type-specific functions (e.g., {@link it.unimi.dsi.fastutil.ints.Int2IntMap}
|
|
+ * extends {@link it.unimi.dsi.fastutil.ints.Int2IntFunction}). However, {@link #size()} is allowed to return -1 to denote
|
|
+ * that the number of keys is not available (e.g., in the case of a string hash function).
|
|
+ *
|
|
+ * <p>Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction} that
|
|
+ * can also set its default return value.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Equality of functions is <em>not specified</em>
|
|
+ * by contract, and it will usually be <em>by reference</em>, as there is no way to enumerate the keys
|
|
+ * and establish whether two functions represent the same mathematical entity.
|
|
+ *
|
|
+ * @see java.util.Map
|
|
+ */
|
|
+
|
|
+public interface Function<K,V> {
|
|
+
|
|
+ /** Associates the specified value with the specified key in this function (optional operation).
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#put(Object,Object)
|
|
+ */
|
|
+
|
|
+ V put( K key, V value );
|
|
+
|
|
+ /** Returns the value associated by this function to the specified key.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#get(Object)
|
|
+ */
|
|
+
|
|
+ V get( Object key );
|
|
+
|
|
+ /** Returns true if this function contains a mapping for the specified key.
|
|
+ *
|
|
+ * <p>Note that for some kind of functions (e.g., hashes) this method
|
|
+ * will always return true.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return true if this function associates a value to <code>key</code>.
|
|
+ * @see java.util.Map#containsKey(Object)
|
|
+ */
|
|
+
|
|
+ boolean containsKey( Object key );
|
|
+
|
|
+ /** Removes this key and the associated value from this function if it is present (optional operation).
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the old value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#remove(Object)
|
|
+ */
|
|
+
|
|
+ V remove( Object key );
|
|
+
|
|
+ /** Returns the intended number of keys in this function, or -1 if no such number exists.
|
|
+ *
|
|
+ * <p>Most function implementations will have some knowledge of the intended number of keys
|
|
+ * in their domain. In some cases, however, this might not be possible.
|
|
+ *
|
|
+ * @return the intended number of keys in this function, or -1 if that number is not available.
|
|
+ */
|
|
+ int size();
|
|
+
|
|
+ /** Removes all associations from this function (optional operation).
|
|
+ *
|
|
+ * @see java.util.Map#clear()
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Hash.java b/src/main/java/it/unimi/dsi/fastutil/Hash.java
|
|
new file mode 100644
|
|
index 0000000..2b52e19
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Hash.java
|
|
@@ -0,0 +1,173 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** Basic data for all hash-based classes.
|
|
+ *
|
|
+ * <h2>Historical note</h2>
|
|
+ *
|
|
+ * <p><strong>Warning:</strong> the following comments are here for historical reasons,
|
|
+ * and apply just to the <em>double hash</em> classes that can be optionally generated.
|
|
+ * The standard <code>fastutil</code> distribution since 6.1.0 uses linear-probing hash
|
|
+ * tables, and tables are always sized as powers of two.
|
|
+ *
|
|
+ * <p>The classes in <code>fastutil</code> are built around open-addressing hashing
|
|
+ * implemented <em>via</em> double hashing. Following Knuth's suggestions in the third volume of <em>The Art of Computer
|
|
+ * Programming</em>, we use for the table size a prime <var>p</var> such that
|
|
+ * <var>p</var>-2 is also prime. In this way hashing is implemented with modulo <var>p</var>,
|
|
+ * and secondary hashing with modulo <var>p</var>-2.
|
|
+ *
|
|
+ * <p>Entries in a table can be in three states: {@link #FREE}, {@link #OCCUPIED} or {@link #REMOVED}.
|
|
+ * The naive handling of removed entries requires that you search for a free entry as if they were occupied. However,
|
|
+ * <code>fastutil</code> implements two useful optimizations, based on the following invariant:
|
|
+ * <blockquote>
|
|
+ * Let <var>i</var><sub>0</sub>, <var>i</var><sub>1</sub>, …, <var>i</var><sub><var>p</var>-1</sub> be
|
|
+ * the permutation of the table indices induced by the key <var>k</var>, that is, <var>i</var><sub>0</sub> is the hash
|
|
+ * of <var>k</var> and the following indices are obtained by adding (modulo <var>p</var>) the secondary hash plus one.
|
|
+ * If there is a {@link #OCCUPIED} entry with key <var>k</var>, its index in the sequence above comes <em>before</em>
|
|
+ * the indices of any {@link #REMOVED} entries with key <var>k</var>.
|
|
+ * </blockquote>
|
|
+ *
|
|
+ * <p>When we search for the key <var>k</var> we scan the entries in the
|
|
+ * sequence <var>i</var><sub>0</sub>, <var>i</var><sub>1</sub>, …,
|
|
+ * <var>i</var><sub><var>p</var>-1</sub> and stop when <var>k</var> is found,
|
|
+ * when we finished the sequence or when we find a {@link #FREE} entry. Note
|
|
+ * that the correctness of this procedure it is not completely trivial. Indeed,
|
|
+ * when we stop at a {@link #REMOVED} entry with key <var>k</var> we must rely
|
|
+ * on the invariant to be sure that no {@link #OCCUPIED} entry with the same
|
|
+ * key can appear later. If we insert and remove frequently the same entries,
|
|
+ * this optimization can be very effective (note, however, that when using
|
|
+ * objects as keys or values deleted entries are set to a special fixed value to
|
|
+ * optimize garbage collection).
|
|
+ *
|
|
+ * <p>Moreover, during the probe we keep the index of the first {@link #REMOVED} entry we meet.
|
|
+ * If we actually have to insert a new element, we use that
|
|
+ * entry if we can, thus avoiding to pollute another {@link #FREE} entry. Since this position comes
|
|
+ * <i>a fortiori</i> before any {@link #REMOVED} entries with the same key, we are also keeping the invariant true.
|
|
+ */
|
|
+
|
|
+public interface Hash {
|
|
+
|
|
+ /** The initial default size of a hash table. */
|
|
+ final public int DEFAULT_INITIAL_SIZE = 16;
|
|
+ /** The default load factor of a hash table. */
|
|
+ final public float DEFAULT_LOAD_FACTOR = .75f;
|
|
+ /** The load factor for a (usually small) table that is meant to be particularly fast. */
|
|
+ final public float FAST_LOAD_FACTOR = .5f;
|
|
+ /** The load factor for a (usually very small) table that is meant to be extremely fast. */
|
|
+ final public float VERY_FAST_LOAD_FACTOR = .25f;
|
|
+
|
|
+ /** A generic hash strategy.
|
|
+ *
|
|
+ * <P>Custom hash structures (e.g., {@link
|
|
+ * it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet}) allow to hash objects
|
|
+ * using arbitrary functions, a typical example being that of {@linkplain
|
|
+ * it.unimi.dsi.fastutil.ints.IntArrays#HASH_STRATEGY arrays}. Of course,
|
|
+ * one has to compare objects for equality consistently with the chosen
|
|
+ * function. A <em>hash strategy</em>, thus, specifies an {@linkplain
|
|
+ * #equals(Object,Object) equality method} and a {@linkplain
|
|
+ * #hashCode(Object) hash function}, with the obvious property that
|
|
+ * equal objects must have the same hash code.
|
|
+ *
|
|
+ * <P>Note that the {@link #equals(Object,Object) equals()} method of a strategy must
|
|
+ * be able to handle <code>null</code>, too.
|
|
+ */
|
|
+
|
|
+ public interface Strategy<K> {
|
|
+
|
|
+ /** Returns the hash code of the specified object with respect to this hash strategy.
|
|
+ *
|
|
+ * @param o an object (or <code>null</code>).
|
|
+ * @return the hash code of the given object with respect to this hash strategy.
|
|
+ */
|
|
+
|
|
+ public int hashCode( K o );
|
|
+
|
|
+ /** Returns true if the given objects are equal with respect to this hash strategy.
|
|
+ *
|
|
+ * @param a an object (or <code>null</code>).
|
|
+ * @param b another object (or <code>null</code>).
|
|
+ * @return true if the two specified objects are equal with respect to this hash strategy.
|
|
+ */
|
|
+ public boolean equals( K a, K b );
|
|
+ }
|
|
+
|
|
+ /** The default growth factor of a hash table. */
|
|
+ final public int DEFAULT_GROWTH_FACTOR = 16;
|
|
+ /** The state of a free hash table entry. */
|
|
+ final public byte FREE = 0;
|
|
+ /** The state of a occupied hash table entry. */
|
|
+ final public byte OCCUPIED = -1;
|
|
+ /** The state of a hash table entry freed by a deletion. */
|
|
+ final public byte REMOVED = 1;
|
|
+
|
|
+ /** A list of primes to be used as table sizes. The <var>i</var>-th element is
|
|
+ * the largest prime <var>p</var> smaller than 2<sup>(<var>i</var>+28)/16</sup>
|
|
+ * and such that <var>p</var>-2 is also prime (or 1, for the first few entries). */
|
|
+
|
|
+ final public int PRIMES[] = { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 7, 7, 7,
|
|
+ 7, 7, 7, 7, 7, 7, 7, 7, 13, 13, 13, 13, 13, 13, 13, 13, 19, 19, 19, 19, 19,
|
|
+ 19, 19, 19, 19, 19, 19, 19, 31, 31, 31, 31, 31, 31, 31, 43, 43, 43, 43, 43,
|
|
+ 43, 43, 43, 61, 61, 61, 61, 61, 73, 73, 73, 73, 73, 73, 73, 103, 103, 109,
|
|
+ 109, 109, 109, 109, 139, 139, 151, 151, 151, 151, 181, 181, 193, 199, 199,
|
|
+ 199, 229, 241, 241, 241, 271, 283, 283, 313, 313, 313, 349, 349, 349, 349,
|
|
+ 421, 433, 463, 463, 463, 523, 523, 571, 601, 619, 661, 661, 661, 661, 661,
|
|
+ 823, 859, 883, 883, 883, 1021, 1063, 1093, 1153, 1153, 1231, 1321, 1321,
|
|
+ 1429, 1489, 1489, 1621, 1699, 1789, 1873, 1951, 2029, 2131, 2143, 2311,
|
|
+ 2383, 2383, 2593, 2731, 2803, 3001, 3121, 3259, 3391, 3583, 3673, 3919,
|
|
+ 4093, 4273, 4423, 4651, 4801, 5023, 5281, 5521, 5743, 5881, 6301, 6571,
|
|
+ 6871, 7129, 7489, 7759, 8089, 8539, 8863, 9283, 9721, 10141, 10531, 11071,
|
|
+ 11551, 12073, 12613, 13009, 13759, 14323, 14869, 15649, 16363, 17029,
|
|
+ 17839, 18541, 19471, 20233, 21193, 22159, 23059, 24181, 25171, 26263,
|
|
+ 27541, 28753, 30013, 31321, 32719, 34213, 35731, 37309, 38923, 40639,
|
|
+ 42463, 44281, 46309, 48313, 50461, 52711, 55051, 57529, 60091, 62299,
|
|
+ 65521, 68281, 71413, 74611, 77713, 81373, 84979, 88663, 92671, 96739,
|
|
+ 100801, 105529, 109849, 115021, 120079, 125509, 131011, 136861, 142873,
|
|
+ 149251, 155863, 162751, 169891, 177433, 185071, 193381, 202129, 211063,
|
|
+ 220021, 229981, 240349, 250969, 262111, 273643, 285841, 298411, 311713,
|
|
+ 325543, 339841, 355009, 370663, 386989, 404269, 422113, 440809, 460081,
|
|
+ 480463, 501829, 524221, 547399, 571603, 596929, 623353, 651019, 679909,
|
|
+ 709741, 741343, 774133, 808441, 844201, 881539, 920743, 961531, 1004119,
|
|
+ 1048573, 1094923, 1143283, 1193911, 1246963, 1302181, 1359733, 1420039,
|
|
+ 1482853, 1548541, 1616899, 1688413, 1763431, 1841293, 1922773, 2008081,
|
|
+ 2097133, 2189989, 2286883, 2388163, 2493853, 2604013, 2719669, 2840041,
|
|
+ 2965603, 3097123, 3234241, 3377191, 3526933, 3682363, 3845983, 4016041,
|
|
+ 4193803, 4379719, 4573873, 4776223, 4987891, 5208523, 5439223, 5680153,
|
|
+ 5931313, 6194191, 6468463, 6754879, 7053331, 7366069, 7692343, 8032639,
|
|
+ 8388451, 8759953, 9147661, 9552733, 9975193, 10417291, 10878619, 11360203,
|
|
+ 11863153, 12387841, 12936529, 13509343, 14107801, 14732413, 15384673,
|
|
+ 16065559, 16777141, 17519893, 18295633, 19105483, 19951231, 20834689,
|
|
+ 21757291, 22720591, 23726449, 24776953, 25873963, 27018853, 28215619,
|
|
+ 29464579, 30769093, 32131711, 33554011, 35039911, 36591211, 38211163,
|
|
+ 39903121, 41669479, 43514521, 45441199, 47452879, 49553941, 51747991,
|
|
+ 54039079, 56431513, 58930021, 61539091, 64263571, 67108669, 70079959,
|
|
+ 73182409, 76422793, 79806229, 83339383, 87029053, 90881083, 94906249,
|
|
+ 99108043, 103495879, 108077731, 112863013, 117860053, 123078019, 128526943,
|
|
+ 134217439, 140159911, 146365159, 152845393, 159612601, 166679173,
|
|
+ 174058849, 181765093, 189812341, 198216103, 206991601, 216156043,
|
|
+ 225726379, 235720159, 246156271, 257054491, 268435009, 280319203,
|
|
+ 292730833, 305691181, 319225021, 333358513, 348117151, 363529759,
|
|
+ 379624279, 396432481, 413983771, 432312511, 451452613, 471440161,
|
|
+ 492312523, 514109251, 536870839, 560640001, 585461743, 611382451,
|
|
+ 638450569, 666717199, 696235363, 727060069, 759249643, 792864871,
|
|
+ 827967631, 864625033, 902905501, 942880663, 984625531, 1028218189,
|
|
+ 1073741719, 1121280091, 1170923713, 1222764841, 1276901371, 1333434301,
|
|
+ 1392470281, 1454120779, 1518500173, 1585729993, 1655935399, 1729249999,
|
|
+ 1805811253, 1885761133, 1969251079, 2056437379, 2147482951 };
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/HashCommon.java b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
|
|
new file mode 100644
|
|
index 0000000..1d42f80
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
|
|
@@ -0,0 +1,240 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** Common code for all hash-based classes. */
|
|
+
|
|
+public class HashCommon {
|
|
+
|
|
+ protected HashCommon() {};
|
|
+
|
|
+ /** This reference is used to fill keys and values of removed entries (if
|
|
+ they are objects). <code>null</code> cannot be used as it would confuse the
|
|
+ search algorithm in the presence of an actual <code>null</code> key. */
|
|
+ public static final Object REMOVED = new Object();
|
|
+
|
|
+ /** 2<sup>32</sup> · φ, φ = (√5 − 1)/2. */
|
|
+ private static final int INT_PHI = 0x9E3779B9;
|
|
+ /** The reciprocal of {@link #INT_PHI} modulo 2<sup>32</sup>. */
|
|
+ private static final int INV_INT_PHI = 0x144cbc89;
|
|
+ /** 2<sup>64</sup> · φ, φ = (√5 − 1)/2. */
|
|
+ private static final long LONG_PHI = 0x9E3779B97F4A7C15L;
|
|
+ /** The reciprocal of {@link #LONG_PHI} modulo 2<sup>64</sup>. */
|
|
+ private static final long INV_LONG_PHI = 0xf1de83e19937733dL;
|
|
+
|
|
+ /** Avalanches the bits of an integer by applying the finalisation step of MurmurHash3.
|
|
+ *
|
|
+ * <p>This method implements the finalisation step of Austin Appleby's <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
|
|
+ * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
|
|
+ *
|
|
+ * @param x an integer.
|
|
+ * @return a hash value with good avalanching properties.
|
|
+ */
|
|
+ public final static int murmurHash3( int x ) {
|
|
+ x ^= x >>> 16;
|
|
+ x *= 0x85ebca6b;
|
|
+ x ^= x >>> 13;
|
|
+ x *= 0xc2b2ae35;
|
|
+ x ^= x >>> 16;
|
|
+ return x;
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Avalanches the bits of a long integer by applying the finalisation step of MurmurHash3.
|
|
+ *
|
|
+ * <p>This method implements the finalisation step of Austin Appleby's <a href="http://code.google.com/p/smhasher/">MurmurHash3</a>.
|
|
+ * Its purpose is to avalanche the bits of the argument to within 0.25% bias.
|
|
+ *
|
|
+ * @param x a long integer.
|
|
+ * @return a hash value with good avalanching properties.
|
|
+ */
|
|
+ public final static long murmurHash3( long x ) {
|
|
+ x ^= x >>> 33;
|
|
+ x *= 0xff51afd7ed558ccdL;
|
|
+ x ^= x >>> 33;
|
|
+ x *= 0xc4ceb9fe1a85ec53L;
|
|
+ x ^= x >>> 33;
|
|
+ return x;
|
|
+ }
|
|
+
|
|
+ /** Quickly mixes the bits of an integer.
|
|
+ *
|
|
+ * <p>This method mixes the bits of the argument by multiplying by the golden ratio and
|
|
+ * xorshifting the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
|
|
+ * it has slightly worse behaviour than {@link #murmurHash3(int)} (in open-addressing hash tables the average number of probes
|
|
+ * is slightly larger), but it's much faster.
|
|
+ *
|
|
+ * @param x an integer.
|
|
+ * @return a hash value obtained by mixing the bits of {@code x}.
|
|
+ * @see #invMix(int)
|
|
+ */
|
|
+ public final static int mix( final int x ) {
|
|
+ final int h = x * INT_PHI;
|
|
+ return h ^ (h >>> 16);
|
|
+ }
|
|
+
|
|
+ /** The inverse of {@link #mix(int)}. This method is mainly useful to create unit tests.
|
|
+ *
|
|
+ * @param x an integer.
|
|
+ * @return a value that passed through {@link #mix(int)} would give {@code x}.
|
|
+ */
|
|
+ public final static int invMix( final int x ) {
|
|
+ return ( x ^ x >>> 16 ) * INV_INT_PHI;
|
|
+ }
|
|
+
|
|
+ /** Quickly mixes the bits of a long integer.
|
|
+ *
|
|
+ * <p>This method mixes the bits of the argument by multiplying by the golden ratio and
|
|
+ * xorshifting twice the result. It is borrowed from <a href="https://github.com/OpenHFT/Koloboke">Koloboke</a>, and
|
|
+ * it has slightly worse behaviour than {@link #murmurHash3(long)} (in open-addressing hash tables the average number of probes
|
|
+ * is slightly larger), but it's much faster.
|
|
+ *
|
|
+ * @param x a long integer.
|
|
+ * @return a hash value obtained by mixing the bits of {@code x}.
|
|
+ */
|
|
+ public final static long mix( final long x ) {
|
|
+ long h = x * LONG_PHI;
|
|
+ h ^= h >>> 32;
|
|
+ return h ^ (h >>> 16);
|
|
+ }
|
|
+
|
|
+ /** The inverse of {@link #mix(long)}. This method is mainly useful to create unit tests.
|
|
+ *
|
|
+ * @param x a long integer.
|
|
+ * @return a value that passed through {@link #mix(long)} would give {@code x}.
|
|
+ */
|
|
+ public final static long invMix( long x ) {
|
|
+ x ^= x >>> 32;
|
|
+ x ^= x >>> 16;
|
|
+ return ( x ^ x >>> 32 ) * INV_LONG_PHI;
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns the hash code that would be returned by {@link Float#hashCode()}.
|
|
+ *
|
|
+ * @param f a float.
|
|
+ * @return the same code as {@link Float#hashCode() new Float(f).hashCode()}.
|
|
+ */
|
|
+
|
|
+ final public static int float2int( final float f ) {
|
|
+ return Float.floatToRawIntBits( f );
|
|
+ }
|
|
+
|
|
+ /** Returns the hash code that would be returned by {@link Double#hashCode()}.
|
|
+ *
|
|
+ * @param d a double.
|
|
+ * @return the same code as {@link Double#hashCode() new Double(f).hashCode()}.
|
|
+ */
|
|
+
|
|
+ final public static int double2int( final double d ) {
|
|
+ final long l = Double.doubleToRawLongBits( d );
|
|
+ return (int)( l ^ ( l >>> 32 ) );
|
|
+ }
|
|
+
|
|
+ /** Returns the hash code that would be returned by {@link Long#hashCode()}.
|
|
+ *
|
|
+ * @param l a long.
|
|
+ * @return the same code as {@link Long#hashCode() new Long(f).hashCode()}.
|
|
+ */
|
|
+ final public static int long2int( final long l ) {
|
|
+ return (int)( l ^ ( l >>> 32 ) );
|
|
+ }
|
|
+
|
|
+ /** Return the least power of two greater than or equal to the specified value.
|
|
+ *
|
|
+ * <p>Note that this function will return 1 when the argument is 0.
|
|
+ *
|
|
+ * @param x an integer smaller than or equal to 2<sup>30</sup>.
|
|
+ * @return the least power of two greater than or equal to the specified value.
|
|
+ */
|
|
+ public static int nextPowerOfTwo( int x ) {
|
|
+ if ( x == 0 ) return 1;
|
|
+ x--;
|
|
+ x |= x >> 1;
|
|
+ x |= x >> 2;
|
|
+ x |= x >> 4;
|
|
+ x |= x >> 8;
|
|
+ return ( x | x >> 16 ) + 1;
|
|
+ }
|
|
+
|
|
+ /** Return the least power of two greater than or equal to the specified value.
|
|
+ *
|
|
+ * <p>Note that this function will return 1 when the argument is 0.
|
|
+ *
|
|
+ * @param x a long integer smaller than or equal to 2<sup>62</sup>.
|
|
+ * @return the least power of two greater than or equal to the specified value.
|
|
+ */
|
|
+ public static long nextPowerOfTwo( long x ) {
|
|
+ if ( x == 0 ) return 1;
|
|
+ x--;
|
|
+ x |= x >> 1;
|
|
+ x |= x >> 2;
|
|
+ x |= x >> 4;
|
|
+ x |= x >> 8;
|
|
+ x |= x >> 16;
|
|
+ return ( x | x >> 32 ) + 1;
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns the maximum number of entries that can be filled before rehashing.
|
|
+ *
|
|
+ * @param n the size of the backing array.
|
|
+ * @param f the load factor.
|
|
+ * @return the maximum number of entries before rehashing.
|
|
+ */
|
|
+ public static int maxFill( final int n, final float f ) {
|
|
+ /* We must guarantee that there is always at least
|
|
+ * one free entry (even with pathological load factors). */
|
|
+ return Math.min( (int)Math.ceil( n * f ), n - 1 );
|
|
+ }
|
|
+
|
|
+ /** Returns the maximum number of entries that can be filled before rehashing.
|
|
+ *
|
|
+ * @param n the size of the backing array.
|
|
+ * @param f the load factor.
|
|
+ * @return the maximum number of entries before rehashing.
|
|
+ */
|
|
+ public static long maxFill( final long n, final float f ) {
|
|
+ /* We must guarantee that there is always at least
|
|
+ * one free entry (even with pathological load factors). */
|
|
+ return Math.min( (long)Math.ceil( n * f ), n - 1 );
|
|
+ }
|
|
+
|
|
+ /** Returns the least power of two smaller than or equal to 2<sup>30</sup> and larger than or equal to <code>Math.ceil( expected / f )</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in a hash table.
|
|
+ * @param f the load factor.
|
|
+ * @return the minimum possible size for a backing array.
|
|
+ * @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
|
|
+ */
|
|
+ public static int arraySize( final int expected, final float f ) {
|
|
+ final long s = Math.max( 2, nextPowerOfTwo( (long)Math.ceil( expected / f ) ) );
|
|
+ if ( s > (1 << 30) ) throw new IllegalArgumentException( "Too large (" + expected + " expected elements with load factor " + f + ")" );
|
|
+ return (int)s;
|
|
+ }
|
|
+
|
|
+ /** Returns the least power of two larger than or equal to <code>Math.ceil( expected / f )</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in a hash table.
|
|
+ * @param f the load factor.
|
|
+ * @return the minimum possible size for a backing big array.
|
|
+ */
|
|
+ public static long bigArraySize( final long expected, final float f ) {
|
|
+ return nextPowerOfTwo( (long)Math.ceil( expected / f ) );
|
|
+ }
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..97ce3c5
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
|
|
@@ -0,0 +1,61 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+
|
|
+/** An indirect double priority queue.
|
|
+ *
|
|
+ * <P>An indirect double priority queue uses two distinct comparators (called <em>primary</em>
|
|
+ * and <em>secondary</em>) to keep its elements ordered. It makes it possible to access the
|
|
+ * first element w.r.t. the secondary comparatory using {@link #secondaryFirst()} (and, optionally,
|
|
+ * the last element using {@link #secondaryLast()}). The remaining methods
|
|
+ * work like those of an {@linkplain it.unimi.dsi.fastutil.IndirectPriorityQueue indirect priority queue} based on the
|
|
+ * primary comparator.
|
|
+ */
|
|
+
|
|
+public interface IndirectDoublePriorityQueue<K> extends IndirectPriorityQueue<K> {
|
|
+
|
|
+ /** Returns the secondary comparator of this queue.
|
|
+ *
|
|
+ * @return the secondary comparator of this queue.
|
|
+ * @see #secondaryFirst()
|
|
+ */
|
|
+ public Comparator<? super K> secondaryComparator();
|
|
+
|
|
+ /** Returns the first element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ *
|
|
+ * @return the first element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ */
|
|
+ public int secondaryFirst();
|
|
+
|
|
+ /** Returns the last element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator} (optional operation).
|
|
+ *
|
|
+ * @return the last element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ */
|
|
+ public int secondaryLast();
|
|
+
|
|
+ /** Retrieves the secondary front of the queue in a given array (optional operation).
|
|
+ *
|
|
+ * @param a an array large enough to hold the secondary front (e.g., at least long as the reference array).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ * @see IndirectPriorityQueue#front(int[])
|
|
+ */
|
|
+
|
|
+ public int secondaryFront( final int[] a );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000..f85a2a7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
|
|
@@ -0,0 +1,110 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with indirect priority queues.
|
|
+ *
|
|
+ * @see IndirectDoublePriorityQueue
|
|
+ */
|
|
+
|
|
+public class IndirectDoublePriorityQueues {
|
|
+
|
|
+ private IndirectDoublePriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty indirect double priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link IndirectDoublePriorityQueue}.
|
|
+ */
|
|
+
|
|
+ public static class EmptyIndirectDoublePriorityQueue extends IndirectPriorityQueues.EmptyIndirectPriorityQueue {
|
|
+
|
|
+ protected EmptyIndirectDoublePriorityQueue() {}
|
|
+
|
|
+ public int secondaryFirst() { throw new NoSuchElementException(); }
|
|
+ public int secondaryLast() { throw new NoSuchElementException(); }
|
|
+ public Comparator<?> secondaryComparator() { return null; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect double priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyIndirectDoublePriorityQueue EMPTY_QUEUE = new EmptyIndirectDoublePriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for indirect double priority queues. */
|
|
+
|
|
+ public static class SynchronizedIndirectDoublePriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected IndirectDoublePriorityQueue<K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( int index ) { synchronized( sync ) { q.enqueue( index ); } }
|
|
+ public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public int first() { synchronized( sync ) { return q.first(); } }
|
|
+ public int last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
|
|
+ public int secondaryFirst() { synchronized( sync ) { return q.secondaryFirst(); } }
|
|
+ public int secondaryLast() { synchronized( sync ) { return q.secondaryLast(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public void allChanged() { synchronized( sync ) { q.allChanged(); } }
|
|
+ public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
|
|
+ public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
|
|
+ public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public Comparator<? super K> secondaryComparator() { synchronized( sync ) { return q.secondaryComparator(); } }
|
|
+ public int secondaryFront( int[] a ) { return q.secondaryFront( a ); }
|
|
+ public int front( int[] a ) { return q.front( a ); }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue.
|
|
+ *
|
|
+ * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
|
|
+ * @return a synchronized view of the specified indirect double priority queue.
|
|
+ */
|
|
+ public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q ) { return new SynchronizedIndirectDoublePriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the indirect double priority queue.
|
|
+ * @return a synchronized view of the specified indirect double priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectDoublePriorityQueue<K>( q, sync ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..74d1a16
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
|
|
@@ -0,0 +1,162 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** An indirect priority queue.
|
|
+ *
|
|
+ * <P>An indirect priority queue provides a way to {@linkplain #enqueue(int)
|
|
+ * enqueue} by index elements taken from a given <em>reference list</em>,
|
|
+ * and to {@linkplain #dequeue() dequeue} them in some specified order.
|
|
+ * Elements that are <em>smaller</em> in the specified order are
|
|
+ * dequeued first. It
|
|
+ * is also possible to get the {@linkplain #first() index of the first element}, that
|
|
+ * is, the index that would be dequeued next.
|
|
+ *
|
|
+ * <P>Additionally, the queue may provide a method to peek at the index of the
|
|
+ * element that would be dequeued {@linkplain #last() last}.
|
|
+ *
|
|
+ * <P>The reference list should not change during queue operations (or, more
|
|
+ * precisely, the relative order of the elements corresponding to indices in the queue should not
|
|
+ * change). Nonetheless, some implementations may give the caller a way to
|
|
+ * notify the queue that the {@linkplain #changed() first element has changed its
|
|
+ * relative position in the order}.
|
|
+ *
|
|
+ * <P>Optionally, an indirect priority queue may even provide methods to notify
|
|
+ * {@linkplain #changed(int) the change of <em>any</em> element of the
|
|
+ * reference list}, to check {@linkplain #contains(int) the presence of
|
|
+ * an index in the queue}, and to {@linkplain #remove(int) remove an index from the queue}.
|
|
+ * It may even allow to notify that {@linkplain #allChanged() all elements have changed}.
|
|
+ *
|
|
+ * <P>It is always possible to enqueue two distinct indices corresponding to
|
|
+ * equal elements of the reference list. However, depending on the
|
|
+ * implementation, it may or may not be possible to enqueue twice the same
|
|
+ * index.
|
|
+ *
|
|
+ * <P>Note that <em>all element manipulation happens via indices</em>.
|
|
+ */
|
|
+
|
|
+public interface IndirectPriorityQueue<K> {
|
|
+
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param index the element to enqueue.
|
|
+ */
|
|
+
|
|
+ void enqueue( int index );
|
|
+
|
|
+ /** Dequeues the {@linkplain #first() first} element from this queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int dequeue();
|
|
+
|
|
+ /** Checks whether this queue is empty.
|
|
+ *
|
|
+ * @return true if this queue is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Returns the number of elements in this queue.
|
|
+ *
|
|
+ * @return the number of elements in this queue.
|
|
+ */
|
|
+
|
|
+ int size();
|
|
+
|
|
+ /** Removes all elements from this queue.
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+ /** Returns the first element of this queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int first();
|
|
+
|
|
+ /** Returns the last element of this queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int last();
|
|
+
|
|
+ /** Notifies this queue that the {@linkplain #first() first element} has changed (optional operation).
|
|
+ *
|
|
+ */
|
|
+
|
|
+ void changed();
|
|
+
|
|
+ /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ */
|
|
+ Comparator <? super K> comparator();
|
|
+
|
|
+ /** Notifies this queue that the specified element has changed (optional operation).
|
|
+ *
|
|
+ * <P>Note that the specified element must belong to this queue.
|
|
+ *
|
|
+ * @param index the element that has changed.
|
|
+ * @throws NoSuchElementException if the specified element is not in this queue.
|
|
+ */
|
|
+
|
|
+ public void changed( int index );
|
|
+
|
|
+ /** Notifies this queue that the all elements have changed (optional operation).
|
|
+ */
|
|
+
|
|
+ public void allChanged();
|
|
+
|
|
+ /** Checks whether a given index belongs to this queue (optional operation).
|
|
+ *
|
|
+ * @param index an index possibly in the queue.
|
|
+ * @return true if the specified index belongs to this queue.
|
|
+ */
|
|
+ public boolean contains( int index );
|
|
+
|
|
+ /** Removes the specified element from this queue (optional operation).
|
|
+ *
|
|
+ * @param index the element to be removed.
|
|
+ * @return true if the index was in the queue.
|
|
+ */
|
|
+
|
|
+ public boolean remove( int index );
|
|
+
|
|
+ /** Retrieves the front of this queue in a given array (optional operation).
|
|
+ *
|
|
+ * <p>The <em>front</em> of an indirect queue is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the {@linkplain #first() first index}. These indices can be always obtain by dequeueing, but
|
|
+ * this method should retrieve efficiently such indices in the given array without modifying the state of this queue.
|
|
+ *
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as the reference array).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+
|
|
+ public int front( final int[] a );
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000..a96837c
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
|
|
@@ -0,0 +1,118 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with indirect priority queues.
|
|
+ *
|
|
+ * @see IndirectPriorityQueue
|
|
+ */
|
|
+
|
|
+public class IndirectPriorityQueues {
|
|
+
|
|
+ private IndirectPriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty indirect priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link IndirectPriorityQueue}.
|
|
+ */
|
|
+
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static class EmptyIndirectPriorityQueue extends AbstractIndirectPriorityQueue {
|
|
+
|
|
+ protected EmptyIndirectPriorityQueue() {}
|
|
+
|
|
+ public void enqueue( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int dequeue() { throw new NoSuchElementException(); }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ public int size() { return 0; }
|
|
+ public boolean contains( int index ) { return false; }
|
|
+ public void clear() {}
|
|
+ public int first() { throw new NoSuchElementException(); }
|
|
+ public int last() { throw new NoSuchElementException(); }
|
|
+ public void changed() { throw new NoSuchElementException(); }
|
|
+ public void allChanged() {}
|
|
+ public Comparator<?> comparator() { return null; }
|
|
+ public void changed( final int i ) { throw new IllegalArgumentException( "Index " + i + " is not in the queue" ); }
|
|
+ public boolean remove( final int i ) { return false; }
|
|
+ public int front( int[] a ) { return 0; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyIndirectPriorityQueue EMPTY_QUEUE = new EmptyIndirectPriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for indirect priority queues. */
|
|
+
|
|
+ public static class SynchronizedIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected IndirectPriorityQueue<K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
|
|
+ public int first() { synchronized( sync ) { return q.first(); } }
|
|
+ public int last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public void allChanged() { synchronized( sync ) { q.allChanged(); } }
|
|
+ public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
|
|
+ public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
|
|
+ public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public int front( int[] a ) { return q.front( a ); }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue.
|
|
+ *
|
|
+ * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
|
|
+ * @return a synchronized view of the specified indirect priority queue.
|
|
+ */
|
|
+ public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q ) { return new SynchronizedIndirectPriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the indirect priority queue.
|
|
+ * @return a synchronized view of the specified indirect priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectPriorityQueue<K>( q, sync ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Maps.java b/src/main/java/it/unimi/dsi/fastutil/Maps.java
|
|
new file mode 100644
|
|
index 0000000..6934251
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Maps.java
|
|
@@ -0,0 +1,36 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+
|
|
+public class Maps {
|
|
+
|
|
+ private Maps() {}
|
|
+
|
|
+ /** A standard default return value to be used in maps containing <code>null</code> values.
|
|
+ * @deprecated Since fastutil 5.0, the introduction of generics
|
|
+ * makes this object pretty useless.
|
|
+ */
|
|
+
|
|
+ @Deprecated
|
|
+ public static final Object MISSING = new Object();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..fe80c6b
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
|
|
@@ -0,0 +1,102 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A priority queue.
|
|
+ *
|
|
+ * <P>A priority queue provides a way to {@linkplain #enqueue(Object) enqueue}
|
|
+ * elements, and to {@linkplain #dequeue() dequeue} them in some specified
|
|
+ * order. Elements that are <em>smaller</em> in the specified order are
|
|
+ * dequeued first. It is also possible to get the {@linkplain #first() first
|
|
+ * element}, that is, the element that would be dequeued next.
|
|
+ *
|
|
+ * <P>Additionally, the queue may provide a method to peek at
|
|
+ * element that would be dequeued {@linkplain #last() last}.
|
|
+ *
|
|
+ * <P>The relative order of the elements enqueued should not change during
|
|
+ * queue operations. Nonetheless, some implementations may give the caller a
|
|
+ * way to notify the queue that the {@linkplain #changed() first element has
|
|
+ * changed its relative position in the order}.
|
|
+ */
|
|
+
|
|
+public interface PriorityQueue<K> {
|
|
+
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue..
|
|
+ */
|
|
+
|
|
+ void enqueue( K x );
|
|
+
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K dequeue();
|
|
+
|
|
+ /** Checks whether the queue is empty.
|
|
+ *
|
|
+ * @return true if the queue is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Returns the number of elements in this queue.
|
|
+ *
|
|
+ * @return the number of elements in this queue.
|
|
+ */
|
|
+
|
|
+ int size();
|
|
+
|
|
+ /** Removes all elements from this queue.
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K first();
|
|
+
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K last();
|
|
+
|
|
+ /** Notifies the queue that the {@linkplain #first() first} element has changed (optional operation).
|
|
+ */
|
|
+
|
|
+ void changed();
|
|
+
|
|
+ /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ */
|
|
+ Comparator<? super K> comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000..eba43d7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
|
|
@@ -0,0 +1,109 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+
|
|
+public class PriorityQueues {
|
|
+
|
|
+ private PriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link PriorityQueue}.
|
|
+ */
|
|
+
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static class EmptyPriorityQueue extends AbstractPriorityQueue {
|
|
+
|
|
+ protected EmptyPriorityQueue() {}
|
|
+
|
|
+ public void enqueue( Object o ) { throw new UnsupportedOperationException(); }
|
|
+ public Object dequeue() { throw new NoSuchElementException(); }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public Object first() { throw new NoSuchElementException(); }
|
|
+ public Object last() { throw new NoSuchElementException(); }
|
|
+ public void changed() { throw new NoSuchElementException(); }
|
|
+ public Comparator<?> comparator() { return null; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyPriorityQueue EMPTY_QUEUE = new EmptyPriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+
|
|
+ public static class SynchronizedPriorityQueue<K> implements PriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected PriorityQueue <K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedPriorityQueue( final PriorityQueue <K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedPriorityQueue( final PriorityQueue <K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( K x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public K dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public K first() { synchronized( sync ) { return q.first(); } }
|
|
+ public K last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public Comparator <? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized priority queue backed by the specified priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q ) { return new SynchronizedPriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized priority queue backed by the specified priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q, final Object sync ) { return new SynchronizedPriorityQueue<K>( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Size64.java b/src/main/java/it/unimi/dsi/fastutil/Size64.java
|
|
new file mode 100644
|
|
index 0000000..05ff4cc
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Size64.java
|
|
@@ -0,0 +1,50 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import java.util.Collection;
|
|
+
|
|
+/** An interface for data structures whose size can exceed {@link Integer#MAX_VALUE}.
|
|
+ *
|
|
+ * <P>The only methods specified by this interfaces are {@link #size64()}, and
|
|
+ * a deprecated {@link #size()} identical to {@link Collection#size()}. Implementations
|
|
+ * can work around the type problem of {@link java.util.Collection#size()}
|
|
+ * (e.g., not being able to return more than {@link Integer#MAX_VALUE}) by implementing this
|
|
+ * interface. Callers interested in large structures
|
|
+ * can use a reflective call to <code>instanceof</code> to check for the presence of {@link #size64()}.
|
|
+ *
|
|
+ * <p>We remark that it is always a good idea to implement both {@link #size()} <em>and</em> {@link #size64()},
|
|
+ * as the former might be implemented by a superclass in an incompatible way. If you implement this interface,
|
|
+ * just implement {@link #size()} as a <em>deprecated</em> method returning <code>Math.min(Integer.MAX_VALUE, size64())</code>.
|
|
+ */
|
|
+
|
|
+public interface Size64 {
|
|
+ /** Returns the size of this data structure as a long.
|
|
+ *
|
|
+ * @return the size of this data structure.
|
|
+ */
|
|
+ long size64();
|
|
+
|
|
+ /** Returns the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
|
|
+ *
|
|
+ * @return the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
|
|
+ * @see java.util.Collection#size()
|
|
+ * @deprecated Use {@link #size64()} instead.
|
|
+ */
|
|
+ @Deprecated
|
|
+ int size();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Stack.java b/src/main/java/it/unimi/dsi/fastutil/Stack.java
|
|
new file mode 100644
|
|
index 0000000..2a601a9
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Stack.java
|
|
@@ -0,0 +1,73 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A stack.
|
|
+ *
|
|
+ * <P>A stack must provide the classical {@link #push(Object)} and
|
|
+ * {@link #pop()} operations, but may be also <em>peekable</em>
|
|
+ * to some extent: it may provide just the {@link #top()} function,
|
|
+ * or even a more powerful {@link #peek(int)} method that provides
|
|
+ * access to all elements on the stack (indexed from the top, which
|
|
+ * has index 0).
|
|
+ */
|
|
+
|
|
+public interface Stack<K> {
|
|
+
|
|
+ /** Pushes the given object on the stack.
|
|
+ *
|
|
+ * @param o the object that will become the new top of the stack.
|
|
+ */
|
|
+
|
|
+ void push( K o );
|
|
+
|
|
+ /** Pops the top off the stack.
|
|
+ *
|
|
+ * @return the top of the stack.
|
|
+ * @throws NoSuchElementException if the stack is empty.
|
|
+ */
|
|
+
|
|
+ K pop();
|
|
+
|
|
+ /** Checks whether the stack is empty.
|
|
+ *
|
|
+ * @return true if the stack is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Peeks at the top of the stack (optional operation).
|
|
+ *
|
|
+ * @return the top of the stack.
|
|
+ * @throws NoSuchElementException if the stack is empty.
|
|
+ */
|
|
+
|
|
+ K top();
|
|
+
|
|
+ /** Peeks at an element on the stack (optional operation).
|
|
+ *
|
|
+ * @param i an index from the stop of the stack (0 represents the top).
|
|
+ * @return the <code>i</code>-th element on the stack.
|
|
+ * @throws IndexOutOfBoundsException if the designated element does not exist..
|
|
+ */
|
|
+
|
|
+ K peek( int i );
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Swapper.java b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
|
|
new file mode 100644
|
|
index 0000000..5d4e2cb
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
|
|
@@ -0,0 +1,31 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An object that can swap elements whose position is specified by integers
|
|
+ *
|
|
+ * @see Arrays#quickSort(int, int, it.unimi.dsi.fastutil.ints.IntComparator, Swapper)
|
|
+ */
|
|
+
|
|
+public interface Swapper {
|
|
+ /** Swaps the data at the given positions.
|
|
+ *
|
|
+ * @param a the first position to swap.
|
|
+ * @param b the second position to swap.
|
|
+ */
|
|
+ void swap( int a, int b );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000..fba1030
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
|
|
@@ -0,0 +1,150 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class providing basic methods for functions implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>This class handles directly a default return
|
|
+ * value (including {@linkplain #defaultReturnValue() methods to access
|
|
+ * it}). Instances of classes inheriting from this class have just to return
|
|
+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
|
|
+ * is serialized.
|
|
+ *
|
|
+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
|
|
+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractInt2ObjectFunction <V> implements Int2ObjectFunction <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractInt2ObjectFunction() {}
|
|
+ /**
|
|
+ * The default return value for <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code>.
|
|
+ */
|
|
+ protected V defRetValue;
|
|
+ public void defaultReturnValue( final V rv ) {
|
|
+ defRetValue = rv;
|
|
+ }
|
|
+ public V defaultReturnValue() {
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public V put( int key, V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public V remove( int key ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public void clear() {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean containsKey( final Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return containsKey( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V get( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ return containsKey( k ) ? (get( k )) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ *
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final int k = ((ok).intValue());
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = put( k, (ov) );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V remove( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = remove( k );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000..9579648
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
|
|
@@ -0,0 +1,271 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for maps implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
|
|
+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
|
|
+ * is particularly useful for those classes that do not implement their own
|
|
+ * entries (e.g., most immutable maps).
|
|
+ */
|
|
+public abstract class AbstractInt2ObjectMap <V> extends AbstractInt2ObjectFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractInt2ObjectMap() {}
|
|
+ /** Checks whether the given value is contained in {@link #values()}. */
|
|
+ public boolean containsValue( Object v ) {
|
|
+ return values().contains( v );
|
|
+ }
|
|
+ /** Checks whether the given value is contained in {@link #keySet()}. */
|
|
+ public boolean containsKey( int k ) {
|
|
+ return keySet().contains( k );
|
|
+ }
|
|
+ /** Puts all pairs in the given map.
|
|
+ * If the map implements the interface of this map,
|
|
+ * it uses the faster iterators.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","deprecation"})
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ int n = m.size();
|
|
+ final Iterator<? extends Map.Entry<? extends Integer,? extends V>> i = m.entrySet().iterator();
|
|
+ if (m instanceof Int2ObjectMap) {
|
|
+ Int2ObjectMap.Entry <? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = (Int2ObjectMap.Entry <? extends V>)i.next();
|
|
+ put(e.getIntKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Map.Entry<? extends Integer,? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = i.next();
|
|
+ put(e.getKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
|
|
+ * that do not have entries on their own (e.g., most immutable maps).
|
|
+ *
|
|
+ * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
|
|
+ * would not be reflected in the base map.
|
|
+ */
|
|
+ public static class BasicEntry <V> implements Int2ObjectMap.Entry <V> {
|
|
+ protected int key;
|
|
+ protected V value;
|
|
+ public BasicEntry( final Integer key, final V value ) {
|
|
+ this.key = ((key).intValue());
|
|
+ this.value = (value);
|
|
+ }
|
|
+ public BasicEntry( final int key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue( final V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "->" + value;
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public IntSet keySet() {
|
|
+ return new AbstractIntSet () {
|
|
+ public boolean contains( final int k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractInt2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectMap.this.clear(); }
|
|
+ public IntIterator iterator() {
|
|
+ return new AbstractIntIterator () {
|
|
+ final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public int nextInt() { return ((Int2ObjectMap.Entry <V>)i.next()).getIntKey(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the values of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new AbstractObjectCollection <V>() {
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractInt2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectMap.this.clear(); }
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new AbstractObjectIterator <V>() {
|
|
+ final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V next() { return ((Int2ObjectMap.Entry <V>)i.next()).getValue(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() {
|
|
+ return (ObjectSet)int2ObjectEntrySet();
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * The hash code of a map is computed by summing the hash codes of its entries.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ while( n-- != 0 ) h += i.next().hashCode();
|
|
+ return h;
|
|
+ }
|
|
+ public boolean equals(Object o) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != size() ) return false;
|
|
+ return entrySet().containsAll( m.entrySet() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ int n = size();
|
|
+ Int2ObjectMap.Entry <V> e;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ e = (Int2ObjectMap.Entry <V>)i.next();
|
|
+ s.append(String.valueOf(e.getIntKey()));
|
|
+ s.append("=>");
|
|
+ if (this == e.getValue()) s.append("(this map)"); else
|
|
+ s.append(String.valueOf(e.getValue()));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000..4b4191b
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
|
|
@@ -0,0 +1,193 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
|
|
+public abstract class AbstractInt2ObjectSortedMap <V> extends AbstractInt2ObjectMap <V> implements Int2ObjectSortedMap <V> {
|
|
+ private static final long serialVersionUID = -1773560792952436569L;
|
|
+ protected AbstractInt2ObjectSortedMap() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( final Integer to ) {
|
|
+ return headMap( ((to).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( final Integer from ) {
|
|
+ return tailMap( ((from).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) {
|
|
+ return subMap( ((from).intValue()), ((to).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() {
|
|
+ return (Integer.valueOf(firstIntKey()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() {
|
|
+ return (Integer.valueOf(lastIntKey()));
|
|
+ }
|
|
+ /** Returns a type-specific-sorted-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public IntSortedSet keySet() {
|
|
+ return new KeySet();
|
|
+ }
|
|
+ /** A wrapper exhibiting the keys of a map. */
|
|
+ protected class KeySet extends AbstractIntSortedSet {
|
|
+ public boolean contains( final int k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
|
|
+ public IntComparator comparator() { return AbstractInt2ObjectSortedMap.this.comparator(); }
|
|
+ public int firstInt() { return firstIntKey(); }
|
|
+ public int lastInt() { return lastIntKey(); }
|
|
+ public IntSortedSet headSet( final int to ) { return headMap( to ).keySet(); }
|
|
+ public IntSortedSet tailSet( final int from ) { return tailMap( from ).keySet(); }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return subMap( from, to ).keySet(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
|
|
+ public IntBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on keys.
|
|
+ *
|
|
+ * <P>To provide an iterator on keys, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class KeySetIterator <V> extends AbstractIntBidirectionalIterator {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
|
|
+ public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public int nextInt() { return ((i.next().getKey()).intValue()); };
|
|
+ public int previousInt() { return ((i.previous().getKey()).intValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ }
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new ValuesCollection();
|
|
+ }
|
|
+ /** A wrapper exhibiting the values of a map. */
|
|
+ protected class ValuesCollection extends AbstractObjectCollection <V> {
|
|
+ public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on values.
|
|
+ *
|
|
+ * <P>To provide an iterator on values, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
|
|
+ public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public V next() { return (i.next().getValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() {
|
|
+ return (ObjectSortedSet)int2ObjectEntrySet();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..ef90e23
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
|
|
@@ -0,0 +1,95 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractIntBidirectionalIterator extends AbstractIntIterator implements IntBidirectionalIterator {
|
|
+ protected AbstractIntBidirectionalIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int previousInt() { return previous().intValue(); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer previous() { return Integer.valueOf( previousInt() ); }
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousInt();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
|
|
new file mode 100644
|
|
index 0000000..b704d10
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
|
|
@@ -0,0 +1,271 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractIntCollection extends AbstractCollection<Integer> implements IntCollection {
|
|
+ protected AbstractIntCollection() {}
|
|
+ public int[] toArray( int a[] ) {
|
|
+ return toIntArray( a );
|
|
+ }
|
|
+ public int[] toIntArray() {
|
|
+ return toIntArray( null );
|
|
+ }
|
|
+ public int[] toIntArray( int a[] ) {
|
|
+ if ( a == null || a.length < size() ) a = new int[ size() ];
|
|
+ IntIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given type-specific collection to this collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ final IntIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.nextInt() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( IntCollection c ) {
|
|
+ final IntIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( ! contains( i.nextInt() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final IntIterator i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.nextInt() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final IntIterator i = c.iterator();
|
|
+ while( n-- != 0 ) if ( rem( i.nextInt() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends Integer> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract IntIterator iterator();
|
|
+ /** Delegates to the type-specific <code>rem()</code> method. */
|
|
+ public boolean remove( Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return rem( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean add( final Integer o ) {
|
|
+ return add( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean rem( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return contains( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ final IntIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() ) if ( k == iterator.nextInt() ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ public boolean rem( final int k ) {
|
|
+ final IntIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() )
|
|
+ if ( k == iterator.nextInt() ) {
|
|
+ iterator.remove();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final IntIterator i = iterator();
|
|
+ int n = size();
|
|
+ int k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextInt();
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
|
|
new file mode 100644
|
|
index 0000000..2eb1121
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
|
|
@@ -0,0 +1,87 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
|
|
+ *
|
|
+ * <P>To create a type-specific comparator you need both a method comparing
|
|
+ * primitive types and a method comparing objects. However, if you have the
|
|
+ * first one you can just inherit from this class and get for free the second
|
|
+ * one.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ */
|
|
+public abstract class AbstractIntComparator implements IntComparator , java.io.Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ protected AbstractIntComparator() {}
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return compare( ok1.intValue(), ok2.intValue() );
|
|
+ }
|
|
+ public abstract int compare( int k1, int k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
|
|
new file mode 100644
|
|
index 0000000..4fc1be5
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
|
|
@@ -0,0 +1,100 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractIntIterator implements IntIterator {
|
|
+ protected AbstractIntIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int nextInt() { return next().intValue(); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer next() { return Integer.valueOf( nextInt() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextInt();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
|
|
new file mode 100644
|
|
index 0000000..4a32979
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
|
|
@@ -0,0 +1,577 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractIntList extends AbstractIntCollection implements IntList , IntStack {
|
|
+ protected AbstractIntList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public int removeInt( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public int set( final int index, final int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends Integer> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends Integer> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public IntListIterator listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractIntList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = pos++ ); }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ AbstractIntList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractIntList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractIntList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final int k ) {
|
|
+ final IntListIterator i = listIterator();
|
|
+ int e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.nextInt();
|
|
+ if ( ( (k) == (e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final int k ) {
|
|
+ IntListIterator i = listIterator( size() );
|
|
+ int e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previousInt();
|
|
+ if ( ( (k) == (e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (0) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new IntSubList ( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ IntListIterator i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.nextInt();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final int a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final int a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final int a[], int offset, int length ) {
|
|
+ IntListIterator i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.nextInt();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ if ( l instanceof IntList ) {
|
|
+ final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
|
|
+ while( s-- != 0 ) if ( i1.nextInt() != i2.nextInt() ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final List<? extends Integer> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof IntList ) {
|
|
+ final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
|
|
+ int r;
|
|
+ int e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.nextInt();
|
|
+ e2 = i2.nextInt();
|
|
+ if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends Integer> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super Integer>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ IntIterator i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ int k = i.nextInt();
|
|
+ h = 31 * h + (k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( int o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public int popInt() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return removeInt( size() - 1 );
|
|
+ }
|
|
+ public int topInt() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return getInt( size() - 1 );
|
|
+ }
|
|
+ public int peekInt( int i ) {
|
|
+ return getInt( size() - 1 - i );
|
|
+ }
|
|
+ public boolean rem( int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeInt( index );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to <code>rem()</code>. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final IntCollection c ) {
|
|
+ return addAll( index, (Collection<? extends Integer>)c );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ return addAll( index, (IntCollection)l );
|
|
+ }
|
|
+ public boolean addAll( final IntCollection c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ public boolean addAll( final IntList l ) {
|
|
+ return addAll( size(), l );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( final int index, final Integer ok ) {
|
|
+ add( index, ok.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer set( final int index, final Integer ok ) {
|
|
+ return (Integer.valueOf(set( index, ok.intValue() )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer get( final int index ) {
|
|
+ return (Integer.valueOf(getInt( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int indexOf( final Object ok) {
|
|
+ return indexOf( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int lastIndexOf( final Object ok ) {
|
|
+ return lastIndexOf( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer remove( final int index ) {
|
|
+ return (Integer.valueOf(removeInt( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Integer o ) {
|
|
+ push( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer pop() {
|
|
+ return Integer.valueOf( popInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer top() {
|
|
+ return Integer.valueOf( topInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer peek( int i ) {
|
|
+ return Integer.valueOf( peekInt( i ) );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final IntIterator i = iterator();
|
|
+ int n = size();
|
|
+ int k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextInt();
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class IntSubList extends AbstractIntList implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final IntList l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public IntSubList( final IntList l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public int getInt( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.getInt( from + index );
|
|
+ }
|
|
+ public int removeInt( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.removeInt( from + index );
|
|
+ }
|
|
+ public int set( int index, int k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final int[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getInt( from + ( last = pos++ ) ); }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getInt( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new IntSubList ( this, from, to );
|
|
+ }
|
|
+ public boolean rem( int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ to--;
|
|
+ l.removeInt( from + index );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ ensureIndex( index );
|
|
+ to += l.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = this.l.addAll( from + index, l );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return this.l.addAll( from + index, l );
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
|
|
new file mode 100644
|
|
index 0000000..981123f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
|
|
@@ -0,0 +1,92 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractIntListIterator extends AbstractIntBidirectionalIterator implements IntListIterator {
|
|
+ protected AbstractIntListIterator() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void set( Integer ok ) { set( ok.intValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( Integer ok ) { add( ok.intValue() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..b3bc90f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
|
|
@@ -0,0 +1,95 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
|
|
+/** An abstract class providing basic methods for priority queues implementing a type-specific interface.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractIntPriorityQueue extends AbstractPriorityQueue<Integer> implements java.io.Serializable, IntPriorityQueue {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public void enqueue( final Integer x ) { enqueue( x.intValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer dequeue() { return (Integer.valueOf(dequeueInt())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() { return (Integer.valueOf(firstInt())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() { return (Integer.valueOf(lastInt())); }
|
|
+ /** Throws an {@link UnsupportedOperationException}. */
|
|
+ public int lastInt() { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
|
|
new file mode 100644
|
|
index 0000000..97f3bff
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
|
|
@@ -0,0 +1,115 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractIntSet extends AbstractIntCollection implements Cloneable, IntSet {
|
|
+ protected AbstractIntSet() {}
|
|
+ public abstract IntIterator iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ IntIterator i = iterator();
|
|
+ int k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.nextInt(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += (k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to <code>remove()</code>.
|
|
+ *
|
|
+ * @param k the element to be removed.
|
|
+ * @return true if the set was modified.
|
|
+ */
|
|
+ public boolean rem( int k ) {
|
|
+ return remove( k );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return remove( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..fb55816
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
|
|
@@ -0,0 +1,110 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractIntSortedSet extends AbstractIntSet implements IntSortedSet {
|
|
+ protected AbstractIntSortedSet() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet headSet( final Integer to ) {
|
|
+ return headSet( to.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet tailSet( final Integer from ) {
|
|
+ return tailSet( from.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) {
|
|
+ return subSet( from.intValue(), to.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() {
|
|
+ return (Integer.valueOf(firstInt()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() {
|
|
+ return (Integer.valueOf(lastInt()));
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract IntBidirectionalIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
|
|
new file mode 100644
|
|
index 0000000..ba0a282
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
|
|
@@ -0,0 +1,112 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.AbstractStack;
|
|
+/** An abstract class providing basic methods for implementing a type-specific stack interface.
|
|
+ *
|
|
+ * <P>To create a type-specific stack, you need both object methods and
|
|
+ * primitive-type methods. However, if you inherit from this class you need
|
|
+ * just one (anyone).
|
|
+ */
|
|
+public abstract class AbstractIntStack extends AbstractStack<Integer> implements IntStack {
|
|
+ protected AbstractIntStack() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Integer o ) {
|
|
+ push( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer pop() {
|
|
+ return Integer.valueOf( popInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer top() {
|
|
+ return Integer.valueOf( topInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer peek( int i ) {
|
|
+ return Integer.valueOf( peekInt( i ) );
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public void push( int k ) {
|
|
+ push( Integer.valueOf( k ) );
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int popInt() {
|
|
+ return pop().intValue();
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int topInt() {
|
|
+ return top().intValue();
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int peekInt( int i ) {
|
|
+ return peek( i ).intValue();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
|
|
new file mode 100644
|
|
index 0000000..fec4cdc
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
|
|
@@ -0,0 +1,1655 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific AVL tree map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
|
|
+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
|
|
+ */
|
|
+public class Int2ObjectAVLTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
|
|
+ /** A reference to the root entry. */
|
|
+ protected transient Entry <V> tree;
|
|
+ /** Number of entries in this map. */
|
|
+ protected int count;
|
|
+ /** The first key in this map. */
|
|
+ protected transient Entry <V> firstEntry;
|
|
+ /** The last key in this map. */
|
|
+ protected transient Entry <V> lastEntry;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** The value of this variable remembers, after a <code>put()</code>
|
|
+ * or a <code>remove()</code>, whether the <em>domain</em> of the map
|
|
+ * has been modified. */
|
|
+ protected transient boolean modified;
|
|
+ /** This map's comparator, as provided in the constructor. */
|
|
+ protected Comparator<? super Integer> storedComparator;
|
|
+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
|
|
+ always a type-specific comparator, so it could be derived from the former by wrapping. */
|
|
+ protected transient IntComparator actualComparator;
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ {
|
|
+ allocatePaths();
|
|
+ }
|
|
+ /** Creates a new empty tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap() {
|
|
+ tree = null;
|
|
+ count = 0;
|
|
+ }
|
|
+ /** Generates the comparator that will be actually used.
|
|
+ *
|
|
+ * <P>When a specific {@link Comparator} is specified and stored in {@link
|
|
+ * #storedComparator}, we must check whether it is type-specific. If it is
|
|
+ * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
|
|
+ * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
|
|
+ * and makes it into a type-specific one.
|
|
+ */
|
|
+ private void setActualComparator() {
|
|
+ /* If the provided comparator is already type-specific, we use it. Otherwise,
|
|
+ we use a wrapper anonymous class to fake that it is type-specific. */
|
|
+ if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
|
|
+ else actualComparator = new IntComparator () {
|
|
+ public int compare( int k1, int k2 ) {
|
|
+ return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
|
|
+ }
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return storedComparator.compare( ok1, ok2 );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Creates a new empty tree map with the given comparator.
|
|
+ *
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Comparator<? super Integer> c ) {
|
|
+ this();
|
|
+ storedComparator = c;
|
|
+ setActualComparator();
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a {@link SortedMap} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final SortedMap<Integer,V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Int2ObjectMap <? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a type-specific sorted map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
|
|
+ this( c );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final int[] k, final V v[] ) {
|
|
+ this( k, v, null );
|
|
+ }
|
|
+ /*
|
|
+ * The following methods implements some basic building blocks used by
|
|
+ * all accessors. They are (and should be maintained) identical to those used in AVLTreeSet.drv.
|
|
+ *
|
|
+ * The put()/remove() code is derived from Ben Pfaff's GNU libavl
|
|
+ * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
|
|
+ * going on, you should have a look at the literate code contained therein
|
|
+ * first.
|
|
+ */
|
|
+ /** Compares two keys in the right way.
|
|
+ *
|
|
+ * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
|
|
+ * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
|
|
+ *
|
|
+ * @param k1 the first key.
|
|
+ * @param k2 the second key.
|
|
+ * @return a number smaller than, equal to or greater than 0, as usual
|
|
+ * (i.e., when k1 < 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; <code>null</code>, otherwise.
|
|
+ *
|
|
+ * @param k the key to search for.
|
|
+ * @return the corresponding entry, or <code>null</code> if no entry with the given key exists.
|
|
+ */
|
|
+ final Entry <V> findKey( final int k ) {
|
|
+ Entry <V> e = tree;
|
|
+ int cmp;
|
|
+ while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) e = cmp < 0 ? e.left() : e.right();
|
|
+ return e;
|
|
+ }
|
|
+ /** Locates a key.
|
|
+ *
|
|
+ * @param k a key.
|
|
+ * @return the last entry on a search for the given key; this will be
|
|
+ * the given key, if it present; otherwise, it will be either the smallest greater key or the greatest smaller key.
|
|
+ */
|
|
+ final Entry <V> locateKey( final int k ) {
|
|
+ Entry <V> e = tree, last = tree;
|
|
+ int cmp = 0;
|
|
+ while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) {
|
|
+ last = e;
|
|
+ e = cmp < 0 ? e.left() : e.right();
|
|
+ }
|
|
+ return cmp == 0 ? e : last;
|
|
+ }
|
|
+ /** This vector remembers the directions followed during
|
|
+ * the current insertion. It suffices for about 2<sup>32</sup> entries. */
|
|
+ private transient boolean dirPath[];
|
|
+ private void allocatePaths() {
|
|
+ dirPath = new boolean[ 48 ];
|
|
+ }
|
|
+ public V put( final int k, final V v ) {
|
|
+ Entry <V> e = add( k );
|
|
+ final V oldValue = e.value;
|
|
+ e.value = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Returns a node with key k in the balanced tree, creating one with defRetValue if necessary.
|
|
+ *
|
|
+ * @param k the key
|
|
+ * @return a node with key k. If a node with key k already exists, then that node is returned,
|
|
+ * otherwise a new node with defRetValue is created ensuring that the tree is balanced
|
|
+ after creation of the node.
|
|
+ */
|
|
+ private Entry <V> add( final int k ) {
|
|
+ /* After execution of this method, modified is true iff a new entry has
|
|
+ been inserted. */
|
|
+ modified = false;
|
|
+ Entry <V> e = null;
|
|
+ if ( tree == null ) { // The case of the empty tree is treated separately.
|
|
+ count++;
|
|
+ e = tree = lastEntry = firstEntry = new Entry <V>( k, defRetValue );
|
|
+ modified = true;
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> p = tree, q = null, y = tree, z = null, w = null;
|
|
+ int cmp, i = 0;
|
|
+ while( true ) {
|
|
+ if ( ( cmp = compare( k, p.key ) ) == 0 ) {
|
|
+ return p;
|
|
+ }
|
|
+ if ( p.balance() != 0 ) {
|
|
+ i = 0;
|
|
+ z = q;
|
|
+ y = p;
|
|
+ }
|
|
+ if ( dirPath[ i++ ] = cmp > 0 ) {
|
|
+ if ( p.succ() ) {
|
|
+ count++;
|
|
+ e = new Entry <V>( k, defRetValue );
|
|
+ modified = true;
|
|
+ if ( p.right == null ) lastEntry = e;
|
|
+ e.left = p;
|
|
+ e.right = p.right;
|
|
+ p.right( e );
|
|
+ break;
|
|
+ }
|
|
+ q = p;
|
|
+ p = p.right;
|
|
+ }
|
|
+ else {
|
|
+ if ( p.pred() ) {
|
|
+ count++;
|
|
+ e = new Entry <V>( k, defRetValue );
|
|
+ modified = true;
|
|
+ if ( p.left == null ) firstEntry = e;
|
|
+ e.right = p;
|
|
+ e.left = p.left;
|
|
+ p.left( e );
|
|
+ break;
|
|
+ }
|
|
+ q = p;
|
|
+ p = p.left;
|
|
+ }
|
|
+ }
|
|
+ p = y;
|
|
+ i = 0;
|
|
+ while( p != e ) {
|
|
+ if ( dirPath[ i ] ) p.incBalance();
|
|
+ else p.decBalance();
|
|
+ p = dirPath[ i++ ] ? p.right : p.left;
|
|
+ }
|
|
+ if ( y.balance() == -2 ) {
|
|
+ Entry <V> x = y.left;
|
|
+ if ( x.balance() == -1 ) {
|
|
+ w = x;
|
|
+ if ( x.succ() ) {
|
|
+ x.succ( false );
|
|
+ y.pred( x );
|
|
+ }
|
|
+ else y.left = x.right;
|
|
+ x.right = y;
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ if ( ASSERTS ) assert x.balance() == 1;
|
|
+ w = x.right;
|
|
+ x.right = w.left;
|
|
+ w.left = x;
|
|
+ y.left = w.right;
|
|
+ w.right = y;
|
|
+ if ( w.balance() == -1 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 1 );
|
|
+ }
|
|
+ else if ( w.balance() == 0 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ x.balance( -1 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ w.balance( 0 );
|
|
+ if ( w.pred() ) {
|
|
+ x.succ( w );
|
|
+ w.pred( false );
|
|
+ }
|
|
+ if ( w.succ() ) {
|
|
+ y.pred( w );
|
|
+ w.succ( false );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else if ( y.balance() == +2 ) {
|
|
+ Entry <V> x = y.right;
|
|
+ if ( x.balance() == 1 ) {
|
|
+ w = x;
|
|
+ if ( x.pred() ) {
|
|
+ x.pred( false );
|
|
+ y.succ( x );
|
|
+ }
|
|
+ else y.right = x.left;
|
|
+ x.left = y;
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ if ( ASSERTS ) assert x.balance() == -1;
|
|
+ w = x.left;
|
|
+ x.left = w.right;
|
|
+ w.right = x;
|
|
+ y.right = w.left;
|
|
+ w.left = y;
|
|
+ if ( w.balance() == 1 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( -1 );
|
|
+ }
|
|
+ else if ( w.balance() == 0 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ x.balance( 1 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ w.balance( 0 );
|
|
+ if ( w.pred() ) {
|
|
+ y.succ( w );
|
|
+ w.pred( false );
|
|
+ }
|
|
+ if ( w.succ() ) {
|
|
+ x.pred( w );
|
|
+ w.succ( false );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else return e;
|
|
+ if ( z == null ) tree = w;
|
|
+ else {
|
|
+ if ( z.left == y ) z.left = w;
|
|
+ else z.right = w;
|
|
+ }
|
|
+ }
|
|
+ if ( ASSERTS ) checkTree( tree );
|
|
+ return e;
|
|
+ }
|
|
+ /** Finds the parent of an entry.
|
|
+ *
|
|
+ * @param e a node of the tree.
|
|
+ * @return the parent of the given node, or <code>null</code> for the root.
|
|
+ */
|
|
+ private Entry <V> parent( final Entry <V> e ) {
|
|
+ if ( e == tree ) return null;
|
|
+ Entry <V> x, y, p;
|
|
+ x = y = e;
|
|
+ while( true ) {
|
|
+ if ( y.succ() ) {
|
|
+ p = y.right;
|
|
+ if ( p == null || p.left != e ) {
|
|
+ while( ! x.pred() ) x = x.left;
|
|
+ p = x.left;
|
|
+ }
|
|
+ return p;
|
|
+ }
|
|
+ else if ( x.pred() ) {
|
|
+ p = x.left;
|
|
+ if ( p == null || p.right != e ) {
|
|
+ while( ! y.succ() ) y = y.right;
|
|
+ p = y.right;
|
|
+ }
|
|
+ return p;
|
|
+ }
|
|
+ x = x.left;
|
|
+ y = y.right;
|
|
+ }
|
|
+ }
|
|
+ /* After execution of this method, {@link #modified} is true iff an entry
|
|
+ has been deleted. */
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ modified = false;
|
|
+ if ( tree == null ) return defRetValue;
|
|
+ int cmp;
|
|
+ Entry <V> p = tree, q = null;
|
|
+ boolean dir = false;
|
|
+ final int kk = k;
|
|
+ while( true ) {
|
|
+ if ( ( cmp = compare( kk, p.key ) ) == 0 ) break;
|
|
+ else if ( dir = cmp > 0 ) {
|
|
+ q = p;
|
|
+ if ( ( p = p.right() ) == null ) return defRetValue;
|
|
+ }
|
|
+ else {
|
|
+ q = p;
|
|
+ if ( ( p = p.left() ) == null ) return defRetValue;
|
|
+ }
|
|
+ }
|
|
+ if ( p.left == null ) firstEntry = p.next();
|
|
+ if ( p.right == null ) lastEntry = p.prev();
|
|
+ if ( p.succ() ) {
|
|
+ if ( p.pred() ) {
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.succ( p.right );
|
|
+ else q.pred( p.left );
|
|
+ }
|
|
+ else tree = dir ? p.right : p.left;
|
|
+ }
|
|
+ else {
|
|
+ p.prev().right = p.right;
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = p.left;
|
|
+ else q.left = p.left;
|
|
+ }
|
|
+ else tree = p.left;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> r = p.right;
|
|
+ if ( r.pred() ) {
|
|
+ r.left = p.left;
|
|
+ r.pred( p.pred() );
|
|
+ if ( ! r.pred() ) r.prev().right = r;
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = r;
|
|
+ else q.left = r;
|
|
+ }
|
|
+ else tree = r;
|
|
+ r.balance( p.balance() );
|
|
+ q = r;
|
|
+ dir = true;
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> s;
|
|
+ while( true ) {
|
|
+ s = r.left;
|
|
+ if ( s.pred() ) break;
|
|
+ r = s;
|
|
+ }
|
|
+ if ( s.succ() ) r.pred( s );
|
|
+ else r.left = s.right;
|
|
+ s.left = p.left;
|
|
+ if ( ! p.pred() ) {
|
|
+ p.prev().right = s;
|
|
+ s.pred( false );
|
|
+ }
|
|
+ s.right = p.right;
|
|
+ s.succ( false );
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = s;
|
|
+ else q.left = s;
|
|
+ }
|
|
+ else tree = s;
|
|
+ s.balance( p.balance() );
|
|
+ q = r;
|
|
+ dir = false;
|
|
+ }
|
|
+ }
|
|
+ Entry <V> y;
|
|
+ while( q != null ) {
|
|
+ y = q;
|
|
+ q = parent( y );
|
|
+ if ( ! dir ) {
|
|
+ dir = q != null && q.left != y;
|
|
+ y.incBalance();
|
|
+ if ( y.balance() == 1 ) break;
|
|
+ else if ( y.balance() == 2 ) {
|
|
+ Entry <V> x = y.right;
|
|
+ if ( ASSERTS ) assert x != null;
|
|
+ if ( x.balance() == -1 ) {
|
|
+ Entry <V> w;
|
|
+ if ( ASSERTS ) assert x.balance() == -1;
|
|
+ w = x.left;
|
|
+ x.left = w.right;
|
|
+ w.right = x;
|
|
+ y.right = w.left;
|
|
+ w.left = y;
|
|
+ if ( w.balance() == 1 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( -1 );
|
|
+ }
|
|
+ else if ( w.balance() == 0 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ if ( ASSERTS ) assert w.balance() == -1;
|
|
+ x.balance( 1 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ w.balance( 0 );
|
|
+ if ( w.pred() ) {
|
|
+ y.succ( w );
|
|
+ w.pred( false );
|
|
+ }
|
|
+ if ( w.succ() ) {
|
|
+ x.pred( w );
|
|
+ w.succ( false );
|
|
+ }
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = w;
|
|
+ else q.left = w;
|
|
+ }
|
|
+ else tree = w;
|
|
+ }
|
|
+ else {
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = x;
|
|
+ else q.left = x;
|
|
+ }
|
|
+ else tree = x;
|
|
+ if ( x.balance() == 0 ) {
|
|
+ y.right = x.left;
|
|
+ x.left = y;
|
|
+ x.balance( -1 );
|
|
+ y.balance( +1 );
|
|
+ break;
|
|
+ }
|
|
+ if ( ASSERTS ) assert x.balance() == 1;
|
|
+ if ( x.pred() ) {
|
|
+ y.succ( true );
|
|
+ x.pred( false );
|
|
+ }
|
|
+ else y.right = x.left;
|
|
+ x.left = y;
|
|
+ y.balance( 0 );
|
|
+ x.balance( 0 );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ dir = q != null && q.left != y;
|
|
+ y.decBalance();
|
|
+ if ( y.balance() == -1 ) break;
|
|
+ else if ( y.balance() == -2 ) {
|
|
+ Entry <V> x = y.left;
|
|
+ if ( ASSERTS ) assert x != null;
|
|
+ if ( x.balance() == 1 ) {
|
|
+ Entry <V> w;
|
|
+ if ( ASSERTS ) assert x.balance() == 1;
|
|
+ w = x.right;
|
|
+ x.right = w.left;
|
|
+ w.left = x;
|
|
+ y.left = w.right;
|
|
+ w.right = y;
|
|
+ if ( w.balance() == -1 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 1 );
|
|
+ }
|
|
+ else if ( w.balance() == 0 ) {
|
|
+ x.balance( 0 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ else {
|
|
+ if ( ASSERTS ) assert w.balance() == 1;
|
|
+ x.balance( -1 );
|
|
+ y.balance( 0 );
|
|
+ }
|
|
+ w.balance( 0 );
|
|
+ if ( w.pred() ) {
|
|
+ x.succ( w );
|
|
+ w.pred( false );
|
|
+ }
|
|
+ if ( w.succ() ) {
|
|
+ y.pred( w );
|
|
+ w.succ( false );
|
|
+ }
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = w;
|
|
+ else q.left = w;
|
|
+ }
|
|
+ else tree = w;
|
|
+ }
|
|
+ else {
|
|
+ if ( q != null ) {
|
|
+ if ( dir ) q.right = x;
|
|
+ else q.left = x;
|
|
+ }
|
|
+ else tree = x;
|
|
+ if ( x.balance() == 0 ) {
|
|
+ y.left = x.right;
|
|
+ x.right = y;
|
|
+ x.balance( +1 );
|
|
+ y.balance( -1 );
|
|
+ break;
|
|
+ }
|
|
+ if ( ASSERTS ) assert x.balance() == -1;
|
|
+ if ( x.succ() ) {
|
|
+ y.pred( true );
|
|
+ x.succ( false );
|
|
+ }
|
|
+ else y.left = x.right;
|
|
+ x.right = y;
|
|
+ y.balance( 0 );
|
|
+ x.balance( 0 );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ modified = true;
|
|
+ count--;
|
|
+ if ( ASSERTS ) checkTree( tree );
|
|
+ return p.value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V oldValue = put( ((ok).intValue()), (ov) );
|
|
+ return modified ? (this.defRetValue) : (oldValue);
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object ok ) {
|
|
+ final V oldValue = remove( ((((Integer)(ok)).intValue())) );
|
|
+ return modified ? (oldValue) : (this.defRetValue);
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final ValueIterator i = new ValueIterator();
|
|
+ V ev;
|
|
+ int j = count;
|
|
+ while( j-- != 0 ) {
|
|
+ ev = i.next();
|
|
+ if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ public void clear() {
|
|
+ count = 0;
|
|
+ tree = null;
|
|
+ entries = null;
|
|
+ values = null;
|
|
+ keys = null;
|
|
+ firstEntry = lastEntry = null;
|
|
+ }
|
|
+ /** This class represent an entry in a tree map.
|
|
+ *
|
|
+ * <P>We use the only "metadata", i.e., {@link Entry#info}, to store
|
|
+ * information about balance, predecessor status and successor status.
|
|
+ *
|
|
+ * <P>Note that since the class is recursive, it can be
|
|
+ * considered equivalently a tree.
|
|
+ */
|
|
+ private static final class Entry <V> implements Cloneable, Int2ObjectMap.Entry <V> {
|
|
+ /** If the bit in this mask is true, {@link #right} points to a successor. */
|
|
+ private final static int SUCC_MASK = 1 << 31;
|
|
+ /** If the bit in this mask is true, {@link #left} points to a predecessor. */
|
|
+ private final static int PRED_MASK = 1 << 30;
|
|
+ /** The bits in this mask hold the node balance info. You can get it just by casting to byte. */
|
|
+ private final static int BALANCE_MASK = 0xFF;
|
|
+ /** The key of this entry. */
|
|
+ int key;
|
|
+ /** The value of this entry. */
|
|
+ V value;
|
|
+ /** The pointers to the left and right subtrees. */
|
|
+ Entry <V> left, right;
|
|
+ /** This integers holds different information in different bits (see {@link #SUCC_MASK}, {@link #PRED_MASK} and {@link #BALANCE_MASK}). */
|
|
+ int info;
|
|
+ Entry() {}
|
|
+ /** Creates a new entry with the given key and value.
|
|
+ *
|
|
+ * @param k a key.
|
|
+ * @param v a value.
|
|
+ */
|
|
+ Entry( final int k, final V v ) {
|
|
+ this.key = k;
|
|
+ this.value = v;
|
|
+ info = SUCC_MASK | PRED_MASK;
|
|
+ }
|
|
+ /** Returns the left subtree.
|
|
+ *
|
|
+ * @return the left subtree (<code>null</code> if the left
|
|
+ * subtree is empty).
|
|
+ */
|
|
+ Entry <V> left() {
|
|
+ return ( info & PRED_MASK ) != 0 ? null : left;
|
|
+ }
|
|
+ /** Returns the right subtree.
|
|
+ *
|
|
+ * @return the right subtree (<code>null</code> if the right
|
|
+ * subtree is empty).
|
|
+ */
|
|
+ Entry <V> right() {
|
|
+ return ( info & SUCC_MASK ) != 0 ? null : right;
|
|
+ }
|
|
+ /** Checks whether the left pointer is really a predecessor.
|
|
+ * @return true if the left pointer is a predecessor.
|
|
+ */
|
|
+ boolean pred() {
|
|
+ return ( info & PRED_MASK ) != 0;
|
|
+ }
|
|
+ /** Checks whether the right pointer is really a successor.
|
|
+ * @return true if the right pointer is a successor.
|
|
+ */
|
|
+ boolean succ() {
|
|
+ return ( info & SUCC_MASK ) != 0;
|
|
+ }
|
|
+ /** Sets whether the left pointer is really a predecessor.
|
|
+ * @param pred if true then the left pointer will be considered a predecessor.
|
|
+ */
|
|
+ void pred( final boolean pred ) {
|
|
+ if ( pred ) info |= PRED_MASK;
|
|
+ else info &= ~PRED_MASK;
|
|
+ }
|
|
+ /** Sets whether the right pointer is really a successor.
|
|
+ * @param succ if true then the right pointer will be considered a successor.
|
|
+ */
|
|
+ void succ( final boolean succ ) {
|
|
+ if ( succ ) info |= SUCC_MASK;
|
|
+ else info &= ~SUCC_MASK;
|
|
+ }
|
|
+ /** Sets the left pointer to a predecessor.
|
|
+ * @param pred the predecessr.
|
|
+ */
|
|
+ void pred( final Entry <V> pred ) {
|
|
+ info |= PRED_MASK;
|
|
+ left = pred;
|
|
+ }
|
|
+ /** Sets the right pointer to a successor.
|
|
+ * @param succ the successor.
|
|
+ */
|
|
+ void succ( final Entry <V> succ ) {
|
|
+ info |= SUCC_MASK;
|
|
+ right = succ;
|
|
+ }
|
|
+ /** Sets the left pointer to the given subtree.
|
|
+ * @param left the new left subtree.
|
|
+ */
|
|
+ void left( final Entry <V> left ) {
|
|
+ info &= ~PRED_MASK;
|
|
+ this.left = left;
|
|
+ }
|
|
+ /** Sets the right pointer to the given subtree.
|
|
+ * @param right the new right subtree.
|
|
+ */
|
|
+ void right( final Entry <V> right ) {
|
|
+ info &= ~SUCC_MASK;
|
|
+ this.right = right;
|
|
+ }
|
|
+ /** Returns the current level of the node.
|
|
+ * @return the current level of this node.
|
|
+ */
|
|
+ int balance() {
|
|
+ return (byte)info;
|
|
+ }
|
|
+ /** Sets the level of this node.
|
|
+ * @param level the new level of this node.
|
|
+ */
|
|
+ void balance( int level ) {
|
|
+ info &= ~BALANCE_MASK;
|
|
+ info |= ( level & BALANCE_MASK );
|
|
+ }
|
|
+ /** Increments the level of this node. */
|
|
+ void incBalance() {
|
|
+ info = info & ~BALANCE_MASK | ( (byte)info + 1 ) & 0xFF;
|
|
+ }
|
|
+ /** Decrements the level of this node. */
|
|
+ protected void decBalance() {
|
|
+ info = info & ~BALANCE_MASK | ( (byte)info - 1 ) & 0xFF;
|
|
+ }
|
|
+ /** Computes the next entry in the set order.
|
|
+ *
|
|
+ * @return the next entry (<code>null</code>) if this is the last entry).
|
|
+ */
|
|
+ Entry <V> next() {
|
|
+ Entry <V> next = this.right;
|
|
+ if ( ( info & SUCC_MASK ) == 0 ) while ( ( next.info & PRED_MASK ) == 0 ) next = next.left;
|
|
+ return next;
|
|
+ }
|
|
+ /** Computes the previous entry in the set order.
|
|
+ *
|
|
+ * @return the previous entry (<code>null</code>) if this is the first entry).
|
|
+ */
|
|
+ Entry <V> prev() {
|
|
+ Entry <V> prev = this.left;
|
|
+ if ( ( info & PRED_MASK ) == 0 ) while ( ( prev.info & SUCC_MASK ) == 0 ) prev = prev.right;
|
|
+ return prev;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue(final V value) {
|
|
+ final V oldValue = this.value;
|
|
+ this.value = value;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> clone() {
|
|
+ Entry <V> c;
|
|
+ try {
|
|
+ c = (Entry <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key;
|
|
+ c.value = value;
|
|
+ c.info = info;
|
|
+ return c;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( (key) == (((e.getKey()).intValue())) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "=>" + value;
|
|
+ }
|
|
+ /*
|
|
+ public void prettyPrint() {
|
|
+ prettyPrint(0);
|
|
+ }
|
|
+
|
|
+ public void prettyPrint(int level) {
|
|
+ if ( pred() ) {
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println("pred: " + left );
|
|
+ }
|
|
+ else if (left != null)
|
|
+ left.prettyPrint(level +1 );
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println(key + "=" + value + " (" + balance() + ")");
|
|
+ if ( succ() ) {
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println("succ: " + right );
|
|
+ }
|
|
+ else if (right != null)
|
|
+ right.prettyPrint(level + 1);
|
|
+ }
|
|
+ */
|
|
+ }
|
|
+ /*
|
|
+ public void prettyPrint() {
|
|
+ System.err.println("size: " + count);
|
|
+ if (tree != null) tree.prettyPrint();
|
|
+ }
|
|
+ */
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return findKey( k ) != null;
|
|
+ }
|
|
+ public int size() {
|
|
+ return count;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return count == 0;
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ final Entry <V> e = findKey( k );
|
|
+ return e == null ? defRetValue : e.value;
|
|
+ }
|
|
+ public int firstIntKey() {
|
|
+ if ( tree == null ) throw new NoSuchElementException();
|
|
+ return firstEntry.key;
|
|
+ }
|
|
+ public int lastIntKey() {
|
|
+ if ( tree == null ) throw new NoSuchElementException();
|
|
+ return lastEntry.key;
|
|
+ }
|
|
+ /** An abstract iterator on the whole range.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a threaded tree.
|
|
+ */
|
|
+ private class TreeIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ Entry <V> prev;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ Entry <V> next;
|
|
+ /** The last entry that was returned (or <code>null</code> if we did not iterate or used {@link #remove()}). */
|
|
+ Entry <V> curr;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this {@link TreeIterator} has been created using the nonempty constructor.*/
|
|
+ int index = 0;
|
|
+ TreeIterator() {
|
|
+ next = firstEntry;
|
|
+ }
|
|
+ TreeIterator( final int k ) {
|
|
+ if ( ( next = locateKey( k ) ) != null ) {
|
|
+ if ( compare( next.key, k ) <= 0 ) {
|
|
+ prev = next;
|
|
+ next = next.next();
|
|
+ }
|
|
+ else prev = next.prev();
|
|
+ }
|
|
+ }
|
|
+ public boolean hasNext() { return next != null; }
|
|
+ public boolean hasPrevious() { return prev != null; }
|
|
+ void updateNext() {
|
|
+ next = next.next();
|
|
+ }
|
|
+ Entry <V> nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = prev = next;
|
|
+ index++;
|
|
+ updateNext();
|
|
+ return curr;
|
|
+ }
|
|
+ void updatePrevious() {
|
|
+ prev = prev.prev();
|
|
+ }
|
|
+ Entry <V> previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = next = prev;
|
|
+ index--;
|
|
+ updatePrevious();
|
|
+ return curr;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == null ) throw new IllegalStateException();
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ if ( curr == prev ) index--;
|
|
+ next = prev = curr;
|
|
+ updatePrevious();
|
|
+ updateNext();
|
|
+ Int2ObjectAVLTreeMap.this.remove( curr.key );
|
|
+ curr = null;
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ /** An iterator on the whole range.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a threaded tree.
|
|
+ */
|
|
+ private class EntryIterator extends TreeIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ EntryIterator() {}
|
|
+ EntryIterator( final int k ) {
|
|
+ super( k );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
|
|
+ final Comparator<? super Int2ObjectMap.Entry <V> > comparator = new Comparator<Int2ObjectMap.Entry <V> > () {
|
|
+ public int compare( final Int2ObjectMap.Entry <V> x, final Int2ObjectMap.Entry <V> y ) {
|
|
+ return Int2ObjectAVLTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() );
|
|
+ }
|
|
+ };
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() {
|
|
+ return comparator;
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ return e.equals( f );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ if ( f != null ) Int2ObjectAVLTreeMap.this.remove( f.key );
|
|
+ return f != null;
|
|
+ }
|
|
+ public int size() { return count; }
|
|
+ public void clear() { Int2ObjectAVLTreeMap.this.clear(); }
|
|
+ public Int2ObjectMap.Entry <V> first() { return firstEntry; }
|
|
+ public Int2ObjectMap.Entry <V> last() { return lastEntry; }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ };
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on the whole range of keys.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the keys of a threaded tree. We
|
|
+ * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
|
|
+ * their type-specific counterparts) so that they return keys instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends TreeIterator implements IntListIterator {
|
|
+ public KeyIterator() {}
|
|
+ public KeyIterator( final int k ) { super( k ); }
|
|
+ public int nextInt() { return nextEntry().key; }
|
|
+ public int previousInt() { return previousEntry().key; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer next() { return (Integer.valueOf(nextEntry().key)); }
|
|
+ public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** A keyset implementation using a more direct implementation for iterators. */
|
|
+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
|
|
+ public IntBidirectionalIterator iterator() { return new KeyIterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new KeyIterator( from ); }
|
|
+ }
|
|
+ /** Returns a type-specific sorted set view of the keys contained in this map.
|
|
+ *
|
|
+ * <P>In addition to the semantics of {@link java.util.Map#keySet()}, you can
|
|
+ * safely cast the set returned by this call to a type-specific sorted
|
|
+ * set interface.
|
|
+ *
|
|
+ * @return a type-specific sorted set view of the keys contained in this map.
|
|
+ */
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on the whole range of values.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the values of a threaded tree. We
|
|
+ * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
|
|
+ * their type-specific counterparts) so that they return values instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends TreeIterator implements ObjectListIterator <V> {
|
|
+ public V next() { return nextEntry().value; }
|
|
+ public V previous() { return previousEntry().value; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>In addition to the semantics of {@link java.util.Map#values()}, you can
|
|
+ * safely cast the collection returned by this call to a type-specific collection
|
|
+ * interface.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return containsValue( k );
|
|
+ }
|
|
+ public int size() {
|
|
+ return count;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectAVLTreeMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ public IntComparator comparator() {
|
|
+ return actualComparator;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> headMap( int to ) {
|
|
+ return new Submap( (0), true, to, false );
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> tailMap( int from ) {
|
|
+ return new Submap( from, false, (0), true );
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
|
|
+ return new Submap( from, false, to, false );
|
|
+ }
|
|
+ /** A submap with given range.
|
|
+ *
|
|
+ * <P>This class represents a submap. One has to specify the left/right
|
|
+ * limits (which can be set to -∞ 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 <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The start of the submap range, unless {@link #bottom} is true. */
|
|
+ int from;
|
|
+ /** The end of the submap range, unless {@link #top} is true. */
|
|
+ int to;
|
|
+ /** If true, the submap range starts from -∞. */
|
|
+ boolean bottom;
|
|
+ /** If true, the submap range goes to ∞. */
|
|
+ boolean top;
|
|
+ /** Cached set of entries. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new submap with given key range.
|
|
+ *
|
|
+ * @param from the start of the submap range.
|
|
+ * @param bottom if true, the first parameter is ignored and the range starts from -∞.
|
|
+ * @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<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new SubmapEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new SubmapEntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return Int2ObjectAVLTreeMap.this.entrySet().comparator(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
|
|
+ final Int2ObjectAVLTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ return f != null && in( f.key ) && e.equals( f );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
|
|
+ final Int2ObjectAVLTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ if ( f != null && in( f.key ) ) Submap.this.remove( f.key );
|
|
+ return f != null;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ for( Iterator<?> i = iterator(); i.hasNext(); i.next() ) c++;
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return ! new SubmapIterator().hasNext();
|
|
+ }
|
|
+ public void clear() {
|
|
+ Submap.this.clear();
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> first() { return firstEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> last() { return lastEntry(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ };
|
|
+ return entries;
|
|
+ }
|
|
+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
|
|
+ public IntBidirectionalIterator iterator() { return new SubmapKeyIterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new SubmapKeyIterator( from ); }
|
|
+ }
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new SubmapValueIterator();
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return containsValue( k );
|
|
+ }
|
|
+ public int size() {
|
|
+ return Submap.this.size();
|
|
+ }
|
|
+ public void clear() {
|
|
+ Submap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return in( k ) && Int2ObjectAVLTreeMap.this.containsKey( k );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final SubmapIterator i = new SubmapIterator();
|
|
+ Object ev;
|
|
+ while( i.hasNext() ) {
|
|
+ ev = i.nextEntry().value;
|
|
+ if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public V get(final int k) {
|
|
+ final Int2ObjectAVLTreeMap.Entry <V> e;
|
|
+ final int kk = k;
|
|
+ return in( kk ) && ( e = findKey( kk ) ) != null ? e.value : this.defRetValue;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ modified = false;
|
|
+ if ( ! in( k ) ) throw new IllegalArgumentException( "Key (" + k + ") out of range [" + ( bottom ? "-" : String.valueOf( from ) ) + ", " + ( top ? "-" : String.valueOf( to ) ) + ")" );
|
|
+ final V oldValue = Int2ObjectAVLTreeMap.this.put( k, v );
|
|
+ return modified ? this.defRetValue : oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V oldValue = put( ((ok).intValue()), (ov) );
|
|
+ return modified ? (this.defRetValue) : (oldValue);
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ modified = false;
|
|
+ if ( ! in( k ) ) return this.defRetValue;
|
|
+ final V oldValue = Int2ObjectAVLTreeMap.this.remove( k );
|
|
+ return modified ? oldValue : this.defRetValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object ok ) {
|
|
+ final V oldValue = remove( ((((Integer)(ok)).intValue())) );
|
|
+ return modified ? (oldValue) : (this.defRetValue);
|
|
+ }
|
|
+ public int size() {
|
|
+ final SubmapIterator i = new SubmapIterator();
|
|
+ int n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ n++;
|
|
+ i.nextEntry();
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return ! new SubmapIterator().hasNext();
|
|
+ }
|
|
+ public IntComparator comparator() {
|
|
+ return actualComparator;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) {
|
|
+ if ( top ) return new Submap( from, bottom, to, false );
|
|
+ return compare( to, this.to ) < 0 ? new Submap( from, bottom, to, false ) : this;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) {
|
|
+ if ( bottom ) return new Submap( from, false, to, top );
|
|
+ return compare( from, this.from ) > 0 ? new Submap( from, false, to, top ) : this;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
|
|
+ if ( top && bottom ) return new Submap( from, false, to, false );
|
|
+ if ( ! top ) to = compare( to, this.to ) < 0 ? to : this.to;
|
|
+ if ( ! bottom ) from = compare( from, this.from ) > 0 ? from : this.from;
|
|
+ if ( ! top && ! bottom && from == this.from && to == this.to ) return this;
|
|
+ return new Submap( from, false, to, false );
|
|
+ }
|
|
+ /** Locates the first entry.
|
|
+ *
|
|
+ * @return the first entry of this submap, or <code>null</code> if the submap is empty.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap.Entry <V> firstEntry() {
|
|
+ if ( tree == null ) return null;
|
|
+ // If this submap goes to -infinity, we return the main map first entry; otherwise, we locate the start of the map.
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e;
|
|
+ if ( bottom ) e = firstEntry;
|
|
+ else {
|
|
+ e = locateKey( from );
|
|
+ // If we find either the start or something greater we're OK.
|
|
+ if ( compare( e.key, from ) < 0 ) e = e.next();
|
|
+ }
|
|
+ // Finally, if this subset doesn't go to infinity, we check that the resulting key isn't greater than the end.
|
|
+ if ( e == null || ! top && compare( e.key, to ) >= 0 ) return null;
|
|
+ return e;
|
|
+ }
|
|
+ /** Locates the last entry.
|
|
+ *
|
|
+ * @return the last entry of this submap, or <code>null</code> if the submap is empty.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap.Entry <V> lastEntry() {
|
|
+ if ( tree == null ) return null;
|
|
+ // If this submap goes to infinity, we return the main map last entry; otherwise, we locate the end of the map.
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e;
|
|
+ if ( top ) e = lastEntry;
|
|
+ else {
|
|
+ e = locateKey( to );
|
|
+ // If we find something smaller than the end we're OK.
|
|
+ if ( compare( e.key, to ) >= 0 ) e = e.prev();
|
|
+ }
|
|
+ // Finally, if this subset doesn't go to -infinity, we check that the resulting key isn't smaller than the start.
|
|
+ if ( e == null || ! bottom && compare( e.key, from ) < 0 ) return null;
|
|
+ return e;
|
|
+ }
|
|
+ public int firstIntKey() {
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e = firstEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.key;
|
|
+ }
|
|
+ public int lastIntKey() {
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e = lastEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.key;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer firstKey() {
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e = firstEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.getKey();
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer lastKey() {
|
|
+ Int2ObjectAVLTreeMap.Entry <V> e = lastEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.getKey();
|
|
+ }
|
|
+ /** An iterator for subranges.
|
|
+ *
|
|
+ * <P>This class inherits from {@link TreeIterator}, but overrides the methods that
|
|
+ * update the pointer after a {@link java.util.ListIterator#next()} or {@link java.util.ListIterator#previous()}. If we would
|
|
+ * move out of the range of the submap we just overwrite the next or previous
|
|
+ * entry with <code>null</code>.
|
|
+ */
|
|
+ private class SubmapIterator extends TreeIterator {
|
|
+ SubmapIterator() {
|
|
+ next = firstEntry();
|
|
+ }
|
|
+ SubmapIterator( final int k ) {
|
|
+ this();
|
|
+ if ( next != null ) {
|
|
+ if ( ! bottom && compare( k, next.key ) < 0 ) prev = null;
|
|
+ else if ( ! top && compare( k, ( prev = lastEntry() ).key ) >= 0 ) next = null;
|
|
+ else {
|
|
+ next = locateKey( k );
|
|
+ if ( compare( next.key, k ) <= 0 ) {
|
|
+ prev = next;
|
|
+ next = next.next();
|
|
+ }
|
|
+ else prev = next.prev();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ void updatePrevious() {
|
|
+ prev = prev.prev();
|
|
+ if ( ! bottom && prev != null && Int2ObjectAVLTreeMap.this.compare( prev.key, from ) < 0 ) prev = null;
|
|
+ }
|
|
+ void updateNext() {
|
|
+ next = next.next();
|
|
+ if ( ! top && next != null && Int2ObjectAVLTreeMap.this.compare( next.key, to ) >= 0 ) next = null;
|
|
+ }
|
|
+ }
|
|
+ private class SubmapEntryIterator extends SubmapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ SubmapEntryIterator() {}
|
|
+ SubmapEntryIterator( final int k ) {
|
|
+ super( k );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** An iterator on a subrange of keys.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a subrange of the
|
|
+ * keys of a threaded tree. We simply override the {@link
|
|
+ * java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
|
|
+ * type-specific counterparts) so that they return keys instead of
|
|
+ * entries.
|
|
+ */
|
|
+ private final class SubmapKeyIterator extends SubmapIterator implements IntListIterator {
|
|
+ public SubmapKeyIterator() { super(); }
|
|
+ public SubmapKeyIterator( int from ) { super( from ); }
|
|
+ public int nextInt() { return nextEntry().key; }
|
|
+ public int previousInt() { return previousEntry().key; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer next() { return (Integer.valueOf(nextEntry().key)); }
|
|
+ public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** An iterator on a subrange of values.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the values of a
|
|
+ * subrange of the keys of a threaded tree. We simply override the
|
|
+ * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
|
|
+ * type-specific counterparts) so that they return values instead of
|
|
+ * entries.
|
|
+ */
|
|
+ private final class SubmapValueIterator extends SubmapIterator implements ObjectListIterator <V> {
|
|
+ public V next() { return nextEntry().value; }
|
|
+ public V previous() { return previousEntry().value; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a deep copy of this tree map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this tree map; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this tree map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectAVLTreeMap <V> clone() {
|
|
+ Int2ObjectAVLTreeMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectAVLTreeMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.allocatePaths();
|
|
+ if ( count != 0 ) {
|
|
+ // Also this apparently unfathomable code is derived from GNU libavl.
|
|
+ Entry <V> e, p, q, rp = new Entry <V>(), rq = new Entry <V>();
|
|
+ p = rp;
|
|
+ rp.left( tree );
|
|
+ q = rq;
|
|
+ rq.pred( null );
|
|
+ while( true ) {
|
|
+ if ( ! p.pred() ) {
|
|
+ e = p.left.clone();
|
|
+ e.pred( q.left );
|
|
+ e.succ( q );
|
|
+ q.left( e );
|
|
+ p = p.left;
|
|
+ q = q.left;
|
|
+ }
|
|
+ else {
|
|
+ while( p.succ() ) {
|
|
+ p = p.right;
|
|
+ if ( p == null ) {
|
|
+ q.right = null;
|
|
+ c.tree = rq.left;
|
|
+ c.firstEntry = c.tree;
|
|
+ while( c.firstEntry.left != null ) c.firstEntry = c.firstEntry.left;
|
|
+ c.lastEntry = c.tree;
|
|
+ while( c.lastEntry.right != null ) c.lastEntry = c.lastEntry.right;
|
|
+ return c;
|
|
+ }
|
|
+ q = q.right;
|
|
+ }
|
|
+ p = p.right;
|
|
+ q = q.right;
|
|
+ }
|
|
+ if ( ! p.succ() ) {
|
|
+ e = p.right.clone();
|
|
+ e.succ( q.right );
|
|
+ e.pred( q );
|
|
+ q.right( e );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ int n = count;
|
|
+ EntryIterator i = new EntryIterator();
|
|
+ Entry <V> e;
|
|
+ s.defaultWriteObject();
|
|
+ while(n-- != 0) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( e.key );
|
|
+ s.writeObject( e.value );
|
|
+ }
|
|
+ }
|
|
+ /** Reads the given number of entries from the input stream, returning the corresponding tree.
|
|
+ *
|
|
+ * @param s the input stream.
|
|
+ * @param n the (positive) number of entries to read.
|
|
+ * @param pred the entry containing the key that preceeds the first key in the tree.
|
|
+ * @param succ the entry containing the key that follows the last key in the tree.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private Entry <V> readTree( final java.io.ObjectInputStream s, final int n, final Entry <V> pred, final Entry <V> succ ) throws java.io.IOException, ClassNotFoundException {
|
|
+ if ( n == 1 ) {
|
|
+ final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
|
|
+ top.pred( pred );
|
|
+ top.succ( succ );
|
|
+ return top;
|
|
+ }
|
|
+ if ( n == 2 ) {
|
|
+ /* We handle separately this case so that recursion will
|
|
+ *always* be on nonempty subtrees. */
|
|
+ final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
|
|
+ top.right( new Entry <V>( s.readInt(), (V) s.readObject() ) );
|
|
+ top.right.pred( top );
|
|
+ top.balance( 1 );
|
|
+ top.pred( pred );
|
|
+ top.right.succ( succ );
|
|
+ return top;
|
|
+ }
|
|
+ // The right subtree is the largest one.
|
|
+ final int rightN = n / 2, leftN = n - rightN - 1;
|
|
+ final Entry <V> top = new Entry <V>();
|
|
+ top.left( readTree( s, leftN, pred, top ) );
|
|
+ top.key = s.readInt();
|
|
+ top.value = (V) s.readObject();
|
|
+ top.right( readTree( s, rightN, top, succ ) );
|
|
+ if ( n == ( n & -n ) ) top.balance( 1 ); // Quick test for determining whether n is a power of 2.
|
|
+ return top;
|
|
+ }
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ /* The storedComparator is now correctly set, but we must restore
|
|
+ on-the-fly the actualComparator. */
|
|
+ setActualComparator();
|
|
+ allocatePaths();
|
|
+ if ( count != 0 ) {
|
|
+ tree = readTree( s, count, null, null );
|
|
+ Entry <V> e;
|
|
+ e = tree;
|
|
+ while( e.left() != null ) e = e.left();
|
|
+ firstEntry = e;
|
|
+ e = tree;
|
|
+ while( e.right() != null ) e = e.right();
|
|
+ lastEntry = e;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTree( tree );
|
|
+ }
|
|
+ private static <V> int checkTree( @SuppressWarnings("unused") Entry <V> e ) { return 0; }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
|
|
new file mode 100644
|
|
index 0000000..2b637a3
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
|
|
@@ -0,0 +1,346 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A simple, brute-force implementation of a map based on two parallel backing arrays.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
|
|
+ */
|
|
+public class Int2ObjectArrayMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The keys (valid up to {@link #size}, excluded). */
|
|
+ private transient int[] key;
|
|
+ /** The values (parallel to {@link #key}). */
|
|
+ private transient Object[] value;
|
|
+ /** The number of valid entries in {@link #key} and {@link #value}. */
|
|
+ private int size;
|
|
+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int[] key, final Object[] value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ size = key.length;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ }
|
|
+ /** Creates a new empty array map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap() {
|
|
+ this.key = IntArrays.EMPTY_ARRAY;
|
|
+ this.value = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array map of given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int capacity ) {
|
|
+ this.key = new int[ capacity ];
|
|
+ this.value = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ * @param size the number of valid elements in <code>key</code> and <code>value</code>.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int[] key, final Object[] value, final int size ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ this.size = size;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
|
|
+ }
|
|
+ private final class EntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ @Override
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
|
|
+ int curr = -1, next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return new AbstractInt2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
|
|
+ int next = 0, curr = -1;
|
|
+ final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ entry.key = key[ curr = next ];
|
|
+ entry.value = (V) value[ next++ ];
|
|
+ return entry;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( Object o ) {
|
|
+ if ( ! ( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ return Int2ObjectArrayMap.this.containsKey( k ) && ( (Int2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Int2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Override
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ final int oldPos = Int2ObjectArrayMap.this.findKey( k );
|
|
+ if ( oldPos == -1 || ! ( (v) == null ? (Int2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Int2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( Int2ObjectArrayMap.this.key, oldPos + 1, Int2ObjectArrayMap.this.key, oldPos, tail );
|
|
+ System.arraycopy( Int2ObjectArrayMap.this.value, oldPos + 1, Int2ObjectArrayMap.this.value, oldPos, tail );
|
|
+ Int2ObjectArrayMap.this.size--;
|
|
+ Int2ObjectArrayMap.this.value[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ return new EntrySet();
|
|
+ }
|
|
+ private int findKey( final int k ) {
|
|
+ final int[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V get( final int k ) {
|
|
+ final int[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ value[ i ] = null;
|
|
+ }
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsValue( Object v ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V put( int k, V v ) {
|
|
+ final int oldKey = findKey( k );
|
|
+ if ( oldKey != -1 ) {
|
|
+ final V oldValue = (V) value[ oldKey ];
|
|
+ value[ oldKey ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ if ( size == key.length ) {
|
|
+ final int[] newKey = new int[ size == 0 ? 2 : size * 2 ];
|
|
+ final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ newKey[ i ] = key[ i ];
|
|
+ newValue[ i ] = value[ i ];
|
|
+ }
|
|
+ key = newKey;
|
|
+ value = newValue;
|
|
+ }
|
|
+ key[ size ] = k;
|
|
+ value[ size ] = v;
|
|
+ size++;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V remove( final int k ) {
|
|
+ final int oldPos = findKey( k );
|
|
+ if ( oldPos == -1 ) return defRetValue;
|
|
+ final V oldValue = (V) value[ oldPos ];
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( key, oldPos + 1, key, oldPos, tail );
|
|
+ System.arraycopy( value, oldPos + 1, value, oldPos, tail );
|
|
+ size--;
|
|
+ value[ size ] = null;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @Override
|
|
+ public IntSet keySet() {
|
|
+ return new IntArraySet ( key, size );
|
|
+ }
|
|
+ @Override
|
|
+ public ObjectCollection <V> values() {
|
|
+ return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectArrayMap <V> clone() {
|
|
+ Int2ObjectArrayMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectArrayMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ s.writeInt( key[ i ] );
|
|
+ s.writeObject( value[ i ] );
|
|
+ }
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ key = new int[ size ];
|
|
+ value = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ key[ i ] = s.readInt();
|
|
+ value[ i ] = s.readObject();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000..489609b
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
|
|
@@ -0,0 +1,137 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Function;
|
|
+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
|
|
+ * a key. Rather, they return a {@linkplain #defaultReturnValue() default
|
|
+ * return value}, which is set to 0 cast to the return type (<code>false</code>
|
|
+ * for booleans) at creation, but can be changed using the
|
|
+ * <code>defaultReturnValue()</code> method.
|
|
+ *
|
|
+ * <P>For uniformity reasons, even maps returning objects implement the default
|
|
+ * return value (of course, in this case the default return value is
|
|
+ * initialized to <code>null</code>).
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
|
|
+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
|
|
+ * that standard versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> for maps with primitive-type values <em>return
|
|
+ * <code>null</code> to denote missing keys</em> rather than wrap the default
|
|
+ * return value in an object (of course, for maps with object keys and values
|
|
+ * this is not possible, as there is no type-specific version).
|
|
+ *
|
|
+ * @see Function
|
|
+ */
|
|
+public interface Int2ObjectFunction <V> extends Function<Integer, V> {
|
|
+ /** Adds a pair to the map.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#put(Object,Object)
|
|
+ */
|
|
+ V put( int key, V value );
|
|
+ /** Returns the value to which the given key is mapped.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#get(Object)
|
|
+ */
|
|
+ V get( int key );
|
|
+ /** Removes the mapping with the given key.
|
|
+ * @param key the key.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#remove(Object)
|
|
+ */
|
|
+ V remove( int key );
|
|
+ /**
|
|
+ * @see Function#containsKey(Object)
|
|
+ */
|
|
+ boolean containsKey( int key );
|
|
+ /** Sets the default return value.
|
|
+ *
|
|
+ * This value must be returned by type-specific versions of
|
|
+ * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
|
|
+ * denote that the map does not contain the specified key. It must be
|
|
+ * 0/<code>false</code>/<code>null</code> by default.
|
|
+ *
|
|
+ * @param rv the new default return value.
|
|
+ * @see #defaultReturnValue()
|
|
+ */
|
|
+ void defaultReturnValue( V rv );
|
|
+ /** Gets the default return value.
|
|
+ *
|
|
+ * @return the current default return value.
|
|
+ */
|
|
+ V defaultReturnValue();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
|
|
new file mode 100644
|
|
index 0000000..d288c35
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
|
|
@@ -0,0 +1,224 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with type-specific functions.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Function
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectFunctions {
|
|
+ private Int2ObjectFunctions() {}
|
|
+ /** An immutable class representing an empty type-specific function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class EmptyFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyFunction() {}
|
|
+ public V get( final int k ) { return (null); }
|
|
+ public boolean containsKey( final int k ) { return false; }
|
|
+ public V defaultReturnValue() { return (null); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return null; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ private Object readResolve() { return EMPTY_FUNCTION; }
|
|
+ public Object clone() { return EMPTY_FUNCTION; }
|
|
+ }
|
|
+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
|
|
+ /** An immutable class representing a type-specific singleton function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class Singleton <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final int key;
|
|
+ protected final V value;
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ public boolean containsKey( final int k ) { return ( (key) == (k) ); }
|
|
+ public V get( final int k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectFunction <V> singleton( final int key, V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectFunction <V> singleton( final Integer key, final V value ) {
|
|
+ return new Singleton <V>( ((key).intValue()), (value) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for functions. */
|
|
+ public static class SynchronizedFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectFunction <V> function;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedFunction( final Int2ObjectFunction <V> f, final Object sync ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedFunction( final Int2ObjectFunction <V> f ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return function.size(); } }
|
|
+ public boolean containsKey( final int k ) { synchronized( sync ) { return function.containsKey( k ); } }
|
|
+ public V defaultReturnValue() { synchronized( sync ) { return function.defaultReturnValue(); } }
|
|
+ public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { function.defaultReturnValue( defRetValue ); } }
|
|
+ public V put( final int k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
|
|
+ public void clear() { synchronized( sync ) { function.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return function.toString(); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
|
|
+ @Override
|
|
+ public V get( final Object k ) { synchronized( sync ) { return function.get( k ); } }
|
|
+ @Override
|
|
+ public V remove( final Object k ) { synchronized( sync ) { return function.remove( k ); } }
|
|
+ @Override
|
|
+ public V remove( final int k ) { synchronized( sync ) { return function.remove( k ); } }
|
|
+ @Override
|
|
+ public V get( final int k ) { synchronized( sync ) { return function.get( k ); } }
|
|
+ public boolean containsKey( final Object ok ) { synchronized( sync ) { return function.containsKey( ok ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific function backed by the given type-specific function.
|
|
+ *
|
|
+ * @param f the function to be wrapped in a synchronized function.
|
|
+ * @return a synchronized view of the specified function.
|
|
+ * @see java.util.Collections#synchronizedMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectFunction <V> synchronize( final Int2ObjectFunction <V> f ) { return new SynchronizedFunction <V>( f ); }
|
|
+ /** Returns a synchronized type-specific function backed by the given type-specific function, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param f the function to be wrapped in a synchronized function.
|
|
+ * @param sync an object that will be used to synchronize the access to the function.
|
|
+ * @return a synchronized view of the specified function.
|
|
+ * @see java.util.Collections#synchronizedMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectFunction <V> synchronize( final Int2ObjectFunction <V> f, final Object sync ) { return new SynchronizedFunction <V>( f, sync ); }
|
|
+ /** An unmodifiable wrapper class for functions. */
|
|
+ public static class UnmodifiableFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectFunction <V> function;
|
|
+ protected UnmodifiableFunction( final Int2ObjectFunction <V> f ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ }
|
|
+ public int size() { return function.size(); }
|
|
+ public boolean containsKey( final int k ) { return function.containsKey( k ); }
|
|
+ public V defaultReturnValue() { return function.defaultReturnValue(); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ public V put( final int k, final V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return function.toString(); }
|
|
+ @Override
|
|
+ public V remove( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final int k ) { return function.get( k ); }
|
|
+ public boolean containsKey( final Object ok ) { return function.containsKey( ok ); }
|
|
+ @Override
|
|
+ public V remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return function.get( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific function backed by the given type-specific function.
|
|
+ *
|
|
+ * @param f the function to be wrapped in an unmodifiable function.
|
|
+ * @return an unmodifiable view of the specified function.
|
|
+ * @see java.util.Collections#unmodifiableMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectFunction <V> unmodifiable( final Int2ObjectFunction <V> f ) { return new UnmodifiableFunction <V>( f ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000..5564407
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
|
|
@@ -0,0 +1,1444 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+/** A type-specific linked hash map with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
|
|
+ * have been added to the map (addition of pairs whose key is already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted map, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first key
|
|
+ * in iteration order with {@code firstKey()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
|
|
+ * contract because all submap methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class using are type-specific
|
|
+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is a key of the map</em>, or
|
|
+ * a {@link NoSuchElementException} exception will be thrown.
|
|
+ * If, however, the provided element is not the first or last key in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire key set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectLinkedOpenHashMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastSortedEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectLinkedOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ private V setValue( final int pos, final V v ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Removes the mapping associated with the first key in iteration order.
|
|
+ * @return the value previously associated with the first key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeFirst() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ /** Removes the mapping associated with the last key in iteration order.
|
|
+ * @return the value previously associated with the last key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeLast() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToFirst( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToLast( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToFirst( final int k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToLast( final int k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * <P>This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first key of this map in iteration order.
|
|
+ *
|
|
+ * @return the first key in iteration order.
|
|
+ */
|
|
+ public int firstIntKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last key of this map in iteration order.
|
|
+ *
|
|
+ * @return the last key in iteration order.
|
|
+ */
|
|
+ public int lastIntKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ public Int2ObjectSortedMap <V> tailMap( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectSortedMap <V> headMap( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ /** A list iterator over a linked map.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
|
|
+ */
|
|
+ private class MapIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
|
|
+ int index = -1;
|
|
+ private MapIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ private MapIterator( final int from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( Int2ObjectLinkedOpenHashMap.this.containsNullKey ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return curr;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ Int2ObjectLinkedOpenHashMap.this.containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public EntryIterator() {}
|
|
+ public EntryIterator( int from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ return entry = new MapEntry( previousEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ final MapEntry entry = new MapEntry();
|
|
+ public FastEntryIterator() {}
|
|
+ public FastEntryIterator( int from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ entry.index = previousEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSortedSet<Int2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return null; }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> fromElement, Int2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectMap.Entry <V> first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Int2ObjectLinkedOpenHashMap.this.first );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> last() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Int2ObjectLinkedOpenHashMap.this.last );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Int2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new FastEntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ }
|
|
+ public FastSortedEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntListIterator {
|
|
+ public KeyIterator( final int k ) { super( k ); }
|
|
+ public int previousInt() { return key[ previousEntry() ]; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer previous() { return (Integer.valueOf(key[ previousEntry() ])); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSortedSet {
|
|
+ public IntListIterator iterator( final int from ) {
|
|
+ return new KeyIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectLinkedOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ final public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ final public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ final public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
|
|
+ public V previous() { return value[ previousEntry() ]; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectLinkedOpenHashMap <V> clone() {
|
|
+ Int2ObjectLinkedOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectLinkedOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = (key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000..b0cba54
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
|
|
@@ -0,0 +1,151 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Map;
|
|
+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
|
|
+ *
|
|
+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
|
|
+ *
|
|
+ * <P>A submap or subset may or may not have an
|
|
+ * independent default return value (which however must be initialized to the
|
|
+ * default return value of the originator).
|
|
+ *
|
|
+ * @see Map
|
|
+ */
|
|
+public interface Int2ObjectMap <V> extends Int2ObjectFunction <V>, Map<Integer,V> {
|
|
+ /** An entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastEntrySet <V> extends ObjectSet<Int2ObjectMap.Entry <V> > {
|
|
+ /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
|
|
+ */
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator();
|
|
+ }
|
|
+ /** Returns a set view of the mappings contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
|
|
+ *
|
|
+ * @return a set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSet<Map.Entry<Integer, V>> entrySet();
|
|
+ /** Returns a type-specific set view of the mappings contained in this map.
|
|
+ *
|
|
+ * <p>This method is necessary because there is no inheritance along
|
|
+ * type parameters: it is thus impossible to strengthen {@link #entrySet()}
|
|
+ * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
|
|
+ * of type-specific entries (the latter makes it possible to
|
|
+ * access keys and values with type-specific methods).
|
|
+ *
|
|
+ * @return a type-specific set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
|
|
+ /** Returns a set view of the keys contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
|
|
+ *
|
|
+ * @return a set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ IntSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * @see java.util.Map.Entry
|
|
+ */
|
|
+ interface Entry <V> extends Map.Entry <Integer,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ Integer getKey();
|
|
+ /**
|
|
+ * @see java.util.Map.Entry#getKey()
|
|
+ */
|
|
+ int getIntKey();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
|
|
new file mode 100644
|
|
index 0000000..2c0741e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
|
|
@@ -0,0 +1,312 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import java.util.Map;
|
|
+/** A class providing static methods and objects that do useful things with type-specific maps.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Maps
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectMaps {
|
|
+ private Int2ObjectMaps() {}
|
|
+ /** An immutable class representing an empty type-specific map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class EmptyMap <V> extends Int2ObjectFunctions.EmptyFunction <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyMap() {}
|
|
+ public boolean containsValue( final Object v ) { return false; }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
|
|
+
|
|
+ public IntSet keySet() { return IntSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_MAP; }
|
|
+ public Object clone() { return EMPTY_MAP; }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ return ((Map<?,?>)o).isEmpty();
|
|
+ }
|
|
+ public String toString() { return "{}"; }
|
|
+ }
|
|
+ /** An empty type-specific map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
|
|
+ /** Return an empty map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Int2ObjectMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Int2ObjectFunctions.Singleton <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ protected transient IntSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ super( key, value );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
|
|
+ public IntSet keySet() { if ( keys == null ) keys = IntSets.singleton( key ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
|
|
+ protected class SingletonEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() { return (Integer.valueOf(Singleton.this.key)); }
|
|
+ public V getValue() { return (Singleton.this.value); }
|
|
+ public int getIntKey() { return Singleton.this.key; }
|
|
+ public V setValue( final V value ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (Singleton.this.key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() { return (Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
|
|
+ public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
|
|
+ }
|
|
+ public boolean isEmpty() { return false; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
|
|
+ public int hashCode() { return (key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != 1 ) return false;
|
|
+ return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
|
|
+ }
|
|
+ public String toString() { return "{" + key + "=>" + value + "}"; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectMap <V> singleton( final int key, V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectMap <V> singleton( final Integer key, final V value ) {
|
|
+ return new Singleton <V>( ((key).intValue()), (value) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for maps. */
|
|
+ public static class SynchronizedMap <V> extends Int2ObjectFunctions.SynchronizedFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectMap <V> map;
|
|
+ protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ protected transient IntSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected SynchronizedMap( final Int2ObjectMap <V> m, final Object sync ) {
|
|
+ super( m, sync );
|
|
+ this.map = m;
|
|
+ }
|
|
+ protected SynchronizedMap( final Int2ObjectMap <V> m ) {
|
|
+ super( m );
|
|
+ this.map = m;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return map.size(); } }
|
|
+ public boolean containsKey( final int k ) { synchronized( sync ) { return map.containsKey( k ); } }
|
|
+ public boolean containsValue( final Object v ) { synchronized( sync ) { return map.containsValue( v ); } }
|
|
+ public V defaultReturnValue() { synchronized( sync ) { return map.defaultReturnValue(); } }
|
|
+ public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { map.defaultReturnValue( defRetValue ); } }
|
|
+ public V put( final int k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
|
|
+ //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { synchronized( sync ) { map.putAll( c ); } }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { synchronized( sync ) { map.putAll( m ); } }
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.synchronize( map.int2ObjectEntrySet(), sync ); return entries; }
|
|
+ public IntSet keySet() { if ( keys == null ) keys = IntSets.synchronize( map.keySet(), sync ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.synchronize( map.values(), sync ); return values; }
|
|
+ public void clear() { synchronized( sync ) { map.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return map.toString(); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final int k ) { synchronized( sync ) { return map.remove( k ); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final int k ) { synchronized( sync ) { return map.get( k ); } }
|
|
+ public boolean containsKey( final Object ok ) { synchronized( sync ) { return map.containsKey( ok ); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return map.isEmpty(); } }
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { synchronized( sync ) { return map.entrySet(); } }
|
|
+ public int hashCode() { synchronized( sync ) { return map.hashCode(); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return map.equals( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific map backed by the given type-specific map.
|
|
+ *
|
|
+ * @param m the map to be wrapped in a synchronized map.
|
|
+ * @return a synchronized view of the specified map.
|
|
+ * @see java.util.Collections#synchronizedMap(Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectMap <V> synchronize( final Int2ObjectMap <V> m ) { return new SynchronizedMap <V>( m ); }
|
|
+ /** Returns a synchronized type-specific map backed by the given type-specific map, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param m the map to be wrapped in a synchronized map.
|
|
+ * @param sync an object that will be used to synchronize the access to the map.
|
|
+ * @return a synchronized view of the specified map.
|
|
+ * @see java.util.Collections#synchronizedMap(Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectMap <V> synchronize( final Int2ObjectMap <V> m, final Object sync ) { return new SynchronizedMap <V>( m, sync ); }
|
|
+ /** An unmodifiable wrapper class for maps. */
|
|
+ public static class UnmodifiableMap <V> extends Int2ObjectFunctions.UnmodifiableFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectMap <V> map;
|
|
+ protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ protected transient IntSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected UnmodifiableMap( final Int2ObjectMap <V> m ) {
|
|
+ super( m );
|
|
+ this.map = m;
|
|
+ }
|
|
+ public int size() { return map.size(); }
|
|
+ public boolean containsKey( final int k ) { return map.containsKey( k ); }
|
|
+ public boolean containsValue( final Object v ) { return map.containsValue( v ); }
|
|
+ public V defaultReturnValue() { throw new UnsupportedOperationException(); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ public V put( final int k, final V v ) { throw new UnsupportedOperationException(); }
|
|
+ //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { throw new UnsupportedOperationException(); }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.unmodifiable( map.int2ObjectEntrySet() ); return entries; }
|
|
+ public IntSet keySet() { if ( keys == null ) keys = IntSets.unmodifiable( map.keySet() ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.unmodifiable( map.values() ); return values; }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return map.toString(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final int k ) { return map.get( k ); }
|
|
+ public boolean containsKey( final Object ok ) { return map.containsKey( ok ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final Object k ) { return map.get( k ); }
|
|
+ public boolean isEmpty() { return map.isEmpty(); }
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { return ObjectSets.unmodifiable( map.entrySet() ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific map backed by the given type-specific map.
|
|
+ *
|
|
+ * @param m the map to be wrapped in an unmodifiable map.
|
|
+ * @return an unmodifiable view of the specified map.
|
|
+ * @see java.util.Collections#unmodifiableMap(Map)
|
|
+ */
|
|
+ public static <V> Int2ObjectMap <V> unmodifiable( final Int2ObjectMap <V> m ) { return new UnmodifiableMap <V>( m ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
|
|
new file mode 100644
|
|
index 0000000..49bebcb
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
|
|
@@ -0,0 +1,922 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectOpenCustomHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The hash strategy of this custom map. */
|
|
+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( k.length, f, strategy );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash map.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( strategy.equals( (key[ index ]), (((e.getKey()).intValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Int2ObjectOpenCustomHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ IntArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final int key[] = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final int k = wrapped.getInt( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Int2ObjectOpenCustomHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Int2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return ( Int2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSet {
|
|
+ public IntIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectOpenCustomHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public IntSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenCustomHashMap <V> clone() {
|
|
+ Int2ObjectOpenCustomHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectOpenCustomHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = ( strategy.hashCode(key[ i ]) );
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000..b392723
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
|
|
@@ -0,0 +1,901 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectOpenHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Int2ObjectOpenHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ IntArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final int key[] = Int2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final int k = wrapped.getInt( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Int2ObjectOpenHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Int2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Int2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSet {
|
|
+ public IntIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public IntSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenHashMap <V> clone() {
|
|
+ Int2ObjectOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = (key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
|
|
new file mode 100644
|
|
index 0000000..dae82fa
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
|
|
@@ -0,0 +1,1599 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific red-black tree map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
|
|
+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
|
|
+ *
|
|
+ */
|
|
+public class Int2ObjectRBTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
|
|
+ /** A reference to the root entry. */
|
|
+ protected transient Entry <V> tree;
|
|
+ /** Number of entries in this map. */
|
|
+ protected int count;
|
|
+ /** The first key in this map. */
|
|
+ protected transient Entry <V> firstEntry;
|
|
+ /** The last key in this map. */
|
|
+ protected transient Entry <V> lastEntry;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** The value of this variable remembers, after a <code>put()</code>
|
|
+ * or a <code>remove()</code>, whether the <em>domain</em> of the map
|
|
+ * has been modified. */
|
|
+ protected transient boolean modified;
|
|
+ /** This map's comparator, as provided in the constructor. */
|
|
+ protected Comparator<? super Integer> storedComparator;
|
|
+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
|
|
+ always a type-specific comparator, so it could be derived from the former by wrapping. */
|
|
+ protected transient IntComparator actualComparator;
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ {
|
|
+ allocatePaths();
|
|
+ }
|
|
+ /** Creates a new empty tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap() {
|
|
+ tree = null;
|
|
+ count = 0;
|
|
+ }
|
|
+ /** Generates the comparator that will be actually used.
|
|
+ *
|
|
+ * <P>When a specific {@link Comparator} is specified and stored in {@link
|
|
+ * #storedComparator}, we must check whether it is type-specific. If it is
|
|
+ * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
|
|
+ * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
|
|
+ * and makes it into a type-specific one.
|
|
+ */
|
|
+ private void setActualComparator() {
|
|
+ /* If the provided comparator is already type-specific, we use it. Otherwise,
|
|
+ we use a wrapper anonymous class to fake that it is type-specific. */
|
|
+ if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
|
|
+ else actualComparator = new IntComparator () {
|
|
+ public int compare( int k1, int k2 ) {
|
|
+ return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
|
|
+ }
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return storedComparator.compare( ok1, ok2 );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Creates a new empty tree map with the given comparator.
|
|
+ *
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Comparator<? super Integer> c ) {
|
|
+ this();
|
|
+ storedComparator = c;
|
|
+ setActualComparator();
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a {@link SortedMap} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final SortedMap<Integer,V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Int2ObjectMap <? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a type-specific sorted map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
|
|
+ this( c );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final int[] k, final V v[] ) {
|
|
+ this( k, v, null );
|
|
+ }
|
|
+ /*
|
|
+ * The following methods implements some basic building blocks used by
|
|
+ * all accessors. They are (and should be maintained) identical to those used in RBTreeSet.drv.
|
|
+ *
|
|
+ * The put()/remove() code is derived from Ben Pfaff's GNU libavl
|
|
+ * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
|
|
+ * going on, you should have a look at the literate code contained therein
|
|
+ * first.
|
|
+ */
|
|
+ /** Compares two keys in the right way.
|
|
+ *
|
|
+ * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
|
|
+ * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
|
|
+ *
|
|
+ * @param k1 the first key.
|
|
+ * @param k2 the second key.
|
|
+ * @return a number smaller than, equal to or greater than 0, as usual
|
|
+ * (i.e., when k1 < 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; <code>null</code>, otherwise.
|
|
+ *
|
|
+ * @param k the key to search for.
|
|
+ * @return the corresponding entry, or <code>null</code> if no entry with the given key exists.
|
|
+ */
|
|
+ final Entry <V> findKey( final int k ) {
|
|
+ Entry <V> e = tree;
|
|
+ int cmp;
|
|
+ while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) e = cmp < 0 ? e.left() : e.right();
|
|
+ return e;
|
|
+ }
|
|
+ /** Locates a key.
|
|
+ *
|
|
+ * @param k a key.
|
|
+ * @return the last entry on a search for the given key; this will be
|
|
+ * the given key, if it present; otherwise, it will be either the smallest greater key or the greatest smaller key.
|
|
+ */
|
|
+ final Entry <V> locateKey( final int k ) {
|
|
+ Entry <V> e = tree, last = tree;
|
|
+ int cmp = 0;
|
|
+ while ( e != null && ( cmp = compare( k, e.key ) ) != 0 ) {
|
|
+ last = e;
|
|
+ e = cmp < 0 ? e.left() : e.right();
|
|
+ }
|
|
+ return cmp == 0 ? e : last;
|
|
+ }
|
|
+ /** This vector remembers the path and the direction followed during the
|
|
+ * current insertion. It suffices for about 2<sup>32</sup> entries. */
|
|
+ private transient boolean dirPath[];
|
|
+ private transient Entry <V> nodePath[];
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void allocatePaths() {
|
|
+ dirPath = new boolean[ 64 ];
|
|
+ nodePath = new Entry[ 64 ];
|
|
+ }
|
|
+ public V put( final int k, final V v ) {
|
|
+ Entry <V> e = add( k );
|
|
+ final V oldValue = e.value;
|
|
+ e.value = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Returns a node with key k in the balanced tree, creating one with defRetValue if necessary.
|
|
+ *
|
|
+ * @param k the key
|
|
+ * @return a node with key k. If a node with key k already exists, then that node is returned,
|
|
+ * otherwise a new node with defRetValue is created ensuring that the tree is balanced
|
|
+ after creation of the node.
|
|
+ */
|
|
+ private Entry <V> add( final int k ) {
|
|
+ /* After execution of this method, modified is true iff a new entry has
|
|
+ been inserted. */
|
|
+ modified = false;
|
|
+ int maxDepth = 0;
|
|
+ Entry <V> e;
|
|
+ if ( tree == null ) { // The case of the empty tree is treated separately.
|
|
+ count++;
|
|
+ e = tree = lastEntry = firstEntry = new Entry <V>( k, defRetValue );
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> p = tree;
|
|
+ int cmp, i = 0;
|
|
+ while( true ) {
|
|
+ if ( ( cmp = compare( k, p.key ) ) == 0 ) {
|
|
+ // We clean up the node path, or we could have stale references later.
|
|
+ while( i-- != 0 ) nodePath[ i ] = null;
|
|
+ return p;
|
|
+ }
|
|
+ nodePath[ i ] = p;
|
|
+ if ( dirPath[ i++ ] = cmp > 0 ) {
|
|
+ if ( p.succ() ) {
|
|
+ count++;
|
|
+ e = new Entry <V>( k, defRetValue );
|
|
+ if ( p.right == null ) lastEntry = e;
|
|
+ e.left = p;
|
|
+ e.right = p.right;
|
|
+ p.right( e );
|
|
+ break;
|
|
+ }
|
|
+ p = p.right;
|
|
+ }
|
|
+ else {
|
|
+ if ( p.pred() ) {
|
|
+ count++;
|
|
+ e = new Entry <V>( k, defRetValue );
|
|
+ if ( p.left == null ) firstEntry = e;
|
|
+ e.right = p;
|
|
+ e.left = p.left;
|
|
+ p.left( e );
|
|
+ break;
|
|
+ }
|
|
+ p = p.left;
|
|
+ }
|
|
+ }
|
|
+ modified = true;
|
|
+ maxDepth = i--;
|
|
+ while( i > 0 && ! nodePath[ i ].black() ) {
|
|
+ if ( ! dirPath[ i - 1 ] ) {
|
|
+ Entry <V> y = nodePath[ i - 1 ].right;
|
|
+ if ( ! nodePath[ i - 1 ].succ() && ! y.black() ) {
|
|
+ nodePath[ i ].black( true );
|
|
+ y.black( true );
|
|
+ nodePath[ i - 1 ].black( false );
|
|
+ i -= 2;
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> x;
|
|
+ if ( ! dirPath[ i ] ) y = nodePath[ i ];
|
|
+ else {
|
|
+ x = nodePath[ i ];
|
|
+ y = x.right;
|
|
+ x.right = y.left;
|
|
+ y.left = x;
|
|
+ nodePath[ i - 1 ].left = y;
|
|
+ if ( y.pred() ) {
|
|
+ y.pred( false );
|
|
+ x.succ( y );
|
|
+ }
|
|
+ }
|
|
+ x = nodePath[ i - 1 ];
|
|
+ x.black( false );
|
|
+ y.black( true );
|
|
+ x.left = y.right;
|
|
+ y.right = x;
|
|
+ if ( i < 2 ) tree = y;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = y;
|
|
+ else nodePath[ i - 2 ].left = y;
|
|
+ }
|
|
+ if ( y.succ() ) {
|
|
+ y.succ( false );
|
|
+ x.pred( y );
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> y = nodePath[ i - 1 ].left;
|
|
+ if ( ! nodePath[ i - 1 ].pred() && ! y.black() ) {
|
|
+ nodePath[ i ].black( true );
|
|
+ y.black( true );
|
|
+ nodePath[ i - 1 ].black( false );
|
|
+ i -= 2;
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> x;
|
|
+ if ( dirPath[ i ] ) y = nodePath[ i ];
|
|
+ else {
|
|
+ x = nodePath[ i ];
|
|
+ y = x.left;
|
|
+ x.left = y.right;
|
|
+ y.right = x;
|
|
+ nodePath[ i - 1 ].right = y;
|
|
+ if ( y.succ() ) {
|
|
+ y.succ( false );
|
|
+ x.pred( y );
|
|
+ }
|
|
+ }
|
|
+ x = nodePath[ i - 1 ];
|
|
+ x.black( false );
|
|
+ y.black( true );
|
|
+ x.right = y.left;
|
|
+ y.left = x;
|
|
+ if ( i < 2 ) tree = y;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = y;
|
|
+ else nodePath[ i - 2 ].left = y;
|
|
+ }
|
|
+ if ( y.pred() ){
|
|
+ y.pred( false );
|
|
+ x.succ( y );
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ tree.black( true );
|
|
+ // We clean up the node path, or we could have stale references later.
|
|
+ while( maxDepth-- != 0 ) nodePath[ maxDepth ] = null;
|
|
+ if ( ASSERTS ) {
|
|
+ checkNodePath();
|
|
+ checkTree( tree, 0, -1 );
|
|
+ }
|
|
+ return e;
|
|
+ }
|
|
+ /* After execution of this method, {@link #modified} is true iff an entry
|
|
+ has been deleted. */
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ modified = false;
|
|
+ if ( tree == null ) return defRetValue;
|
|
+ Entry <V> p = tree;
|
|
+ int cmp;
|
|
+ int i = 0;
|
|
+ final int kk = k;
|
|
+ while( true ) {
|
|
+ if ( ( cmp = compare( kk, p.key ) ) == 0 ) break;
|
|
+ dirPath[ i ] = cmp > 0;
|
|
+ nodePath[ i ] = p;
|
|
+ if ( dirPath[ i++ ] ) {
|
|
+ if ( ( p = p.right() ) == null ) {
|
|
+ // We clean up the node path, or we could have stale references later.
|
|
+ while( i-- != 0 ) nodePath[ i ] = null;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ if ( ( p = p.left() ) == null ) {
|
|
+ // We clean up the node path, or we could have stale references later.
|
|
+ while( i-- != 0 ) nodePath[ i ] = null;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if ( p.left == null ) firstEntry = p.next();
|
|
+ if ( p.right == null ) lastEntry = p.prev();
|
|
+ if ( p.succ() ) {
|
|
+ if ( p.pred() ) {
|
|
+ if ( i == 0 ) tree = p.left;
|
|
+ else {
|
|
+ if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].succ( p.right );
|
|
+ else nodePath[ i - 1 ].pred( p.left );
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ p.prev().right = p.right;
|
|
+ if ( i == 0 ) tree = p.left;
|
|
+ else {
|
|
+ if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].right = p.left;
|
|
+ else nodePath[ i - 1 ].left = p.left;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ boolean color;
|
|
+ Entry <V> r = p.right;
|
|
+ if ( r.pred() ) {
|
|
+ r.left = p.left;
|
|
+ r.pred( p.pred() );
|
|
+ if ( ! r.pred() ) r.prev().right = r;
|
|
+ if ( i == 0 ) tree = r;
|
|
+ else {
|
|
+ if ( dirPath[ i - 1 ] ) nodePath[ i - 1 ].right = r;
|
|
+ else nodePath[ i - 1 ].left = r;
|
|
+ }
|
|
+ color = r.black();
|
|
+ r.black( p.black() );
|
|
+ p.black( color );
|
|
+ dirPath[ i ] = true;
|
|
+ nodePath[ i++ ] = r;
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> s;
|
|
+ int j = i++;
|
|
+ while( true ) {
|
|
+ dirPath[ i ] = false;
|
|
+ nodePath[ i++ ] = r;
|
|
+ s = r.left;
|
|
+ if ( s.pred() ) break;
|
|
+ r = s;
|
|
+ }
|
|
+ dirPath[ j ] = true;
|
|
+ nodePath[ j ] = s;
|
|
+ if ( s.succ() ) r.pred( s );
|
|
+ else r.left = s.right;
|
|
+ s.left = p.left;
|
|
+ if ( ! p.pred() ) {
|
|
+ p.prev().right = s;
|
|
+ s.pred( false );
|
|
+ }
|
|
+ s.right( p.right );
|
|
+ color = s.black();
|
|
+ s.black( p.black() );
|
|
+ p.black( color );
|
|
+ if ( j == 0 ) tree = s;
|
|
+ else {
|
|
+ if ( dirPath[ j - 1 ] ) nodePath[ j - 1 ].right = s;
|
|
+ else nodePath[ j - 1 ].left = s;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ int maxDepth = i;
|
|
+ if ( p.black() ) {
|
|
+ for( ; i > 0; i-- ) {
|
|
+ if ( dirPath[ i - 1 ] && ! nodePath[ i - 1 ].succ() ||
|
|
+ ! dirPath[ i - 1 ] && ! nodePath[ i - 1 ].pred() ) {
|
|
+ Entry <V> x = dirPath[ i - 1 ] ? nodePath[ i - 1 ].right : nodePath[ i - 1 ].left;
|
|
+ if ( ! x.black() ) {
|
|
+ x.black( true );
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if ( ! dirPath[ i - 1 ] ) {
|
|
+ Entry <V> w = nodePath[ i - 1 ].right;
|
|
+ if ( ! w.black() ) {
|
|
+ w.black( true );
|
|
+ nodePath[ i - 1 ].black( false );
|
|
+ nodePath[ i - 1 ].right = w.left;
|
|
+ w.left = nodePath[ i - 1 ];
|
|
+ if ( i < 2 ) tree = w;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
|
|
+ else nodePath[ i - 2 ].left = w;
|
|
+ }
|
|
+ nodePath[ i ] = nodePath[ i - 1 ];
|
|
+ dirPath[ i ] = false;
|
|
+ nodePath[ i - 1 ] = w;
|
|
+ if ( maxDepth == i++ ) maxDepth++;
|
|
+ w = nodePath[ i - 1 ].right;
|
|
+ }
|
|
+ if ( ( w.pred() || w.left.black() ) &&
|
|
+ ( w.succ() || w.right.black() ) ) {
|
|
+ w.black( false );
|
|
+ }
|
|
+ else {
|
|
+ if ( w.succ() || w.right.black() ) {
|
|
+ Entry <V> y = w.left;
|
|
+ y.black ( true );
|
|
+ w.black( false );
|
|
+ w.left = y.right;
|
|
+ y.right = w;
|
|
+ w = nodePath[ i - 1 ].right = y;
|
|
+ if ( w.succ() ) {
|
|
+ w.succ( false );
|
|
+ w.right.pred( w );
|
|
+ }
|
|
+ }
|
|
+ w.black( nodePath[ i - 1 ].black() );
|
|
+ nodePath[ i - 1 ].black( true );
|
|
+ w.right.black( true );
|
|
+ nodePath[ i - 1 ].right = w.left;
|
|
+ w.left = nodePath[ i - 1 ];
|
|
+ if ( i < 2 ) tree = w;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
|
|
+ else nodePath[ i - 2 ].left = w;
|
|
+ }
|
|
+ if ( w.pred() ) {
|
|
+ w.pred( false );
|
|
+ nodePath[ i - 1 ].succ( w );
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Entry <V> w = nodePath[ i - 1 ].left;
|
|
+ if ( ! w.black() ) {
|
|
+ w.black ( true );
|
|
+ nodePath[ i - 1 ].black( false );
|
|
+ nodePath[ i - 1 ].left = w.right;
|
|
+ w.right = nodePath[ i - 1 ];
|
|
+ if ( i < 2 ) tree = w;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
|
|
+ else nodePath[ i - 2 ].left = w;
|
|
+ }
|
|
+ nodePath[ i ] = nodePath[ i - 1 ];
|
|
+ dirPath[ i ] = true;
|
|
+ nodePath[ i - 1 ] = w;
|
|
+ if ( maxDepth == i++ ) maxDepth++;
|
|
+ w = nodePath[ i - 1 ].left;
|
|
+ }
|
|
+ if ( ( w.pred() || w.left.black() ) &&
|
|
+ ( w.succ() || w.right.black() ) ) {
|
|
+ w.black( false );
|
|
+ }
|
|
+ else {
|
|
+ if ( w.pred() || w.left.black() ) {
|
|
+ Entry <V> y = w.right;
|
|
+ y.black( true );
|
|
+ w.black ( false );
|
|
+ w.right = y.left;
|
|
+ y.left = w;
|
|
+ w = nodePath[ i - 1 ].left = y;
|
|
+ if ( w.pred() ) {
|
|
+ w.pred( false );
|
|
+ w.left.succ( w );
|
|
+ }
|
|
+ }
|
|
+ w.black( nodePath[ i - 1 ].black() );
|
|
+ nodePath[ i - 1 ].black( true );
|
|
+ w.left.black( true );
|
|
+ nodePath[ i - 1 ].left = w.right;
|
|
+ w.right = nodePath[ i - 1 ];
|
|
+ if ( i < 2 ) tree = w;
|
|
+ else {
|
|
+ if ( dirPath[ i - 2 ] ) nodePath[ i - 2 ].right = w;
|
|
+ else nodePath[ i - 2 ].left = w;
|
|
+ }
|
|
+ if ( w.succ() ) {
|
|
+ w.succ( false );
|
|
+ nodePath[ i - 1 ].pred( w );
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if ( tree != null ) tree.black( true );
|
|
+ }
|
|
+ modified = true;
|
|
+ count--;
|
|
+ // We clean up the node path, or we could have stale references later.
|
|
+ while( maxDepth-- != 0 ) nodePath[ maxDepth ] = null;
|
|
+ if ( ASSERTS ) {
|
|
+ checkNodePath();
|
|
+ checkTree( tree, 0, -1 );
|
|
+ }
|
|
+ return p.value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V oldValue = put( ((ok).intValue()), (ov) );
|
|
+ return modified ? (this.defRetValue) : (oldValue);
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object ok ) {
|
|
+ final V oldValue = remove( ((((Integer)(ok)).intValue())) );
|
|
+ return modified ? (oldValue) : (this.defRetValue);
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final ValueIterator i = new ValueIterator();
|
|
+ Object ev;
|
|
+ int j = count;
|
|
+ while( j-- != 0 ) {
|
|
+ ev = i.next();
|
|
+ if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ public void clear() {
|
|
+ count = 0;
|
|
+ tree = null;
|
|
+ entries = null;
|
|
+ values = null;
|
|
+ keys = null;
|
|
+ firstEntry = lastEntry = null;
|
|
+ }
|
|
+ /** This class represent an entry in a tree map.
|
|
+ *
|
|
+ * <P>We use the only "metadata", i.e., {@link Entry#info}, to store
|
|
+ * information about color, predecessor status and successor status.
|
|
+ *
|
|
+ * <P>Note that since the class is recursive, it can be
|
|
+ * considered equivalently a tree.
|
|
+ */
|
|
+ private static final class Entry <V> implements Cloneable, Int2ObjectMap.Entry <V> {
|
|
+ /** The the bit in this mask is true, the node is black. */
|
|
+ private final static int BLACK_MASK = 1;
|
|
+ /** If the bit in this mask is true, {@link #right} points to a successor. */
|
|
+ private final static int SUCC_MASK = 1 << 31;
|
|
+ /** If the bit in this mask is true, {@link #left} points to a predecessor. */
|
|
+ private final static int PRED_MASK = 1 << 30;
|
|
+ /** The key of this entry. */
|
|
+ int key;
|
|
+ /** The value of this entry. */
|
|
+ V value;
|
|
+ /** The pointers to the left and right subtrees. */
|
|
+ Entry <V> left, right;
|
|
+ /** This integers holds different information in different bits (see {@link #SUCC_MASK} and {@link #PRED_MASK}. */
|
|
+ int info;
|
|
+ Entry() {}
|
|
+ /** Creates a new entry with the given key and value.
|
|
+ *
|
|
+ * @param k a key.
|
|
+ * @param v a value.
|
|
+ */
|
|
+ Entry( final int k, final V v ) {
|
|
+ this.key = k;
|
|
+ this.value = v;
|
|
+ info = SUCC_MASK | PRED_MASK;
|
|
+ }
|
|
+ /** Returns the left subtree.
|
|
+ *
|
|
+ * @return the left subtree (<code>null</code> if the left
|
|
+ * subtree is empty).
|
|
+ */
|
|
+ Entry <V> left() {
|
|
+ return ( info & PRED_MASK ) != 0 ? null : left;
|
|
+ }
|
|
+ /** Returns the right subtree.
|
|
+ *
|
|
+ * @return the right subtree (<code>null</code> if the right
|
|
+ * subtree is empty).
|
|
+ */
|
|
+ Entry <V> right() {
|
|
+ return ( info & SUCC_MASK ) != 0 ? null : right;
|
|
+ }
|
|
+ /** Checks whether the left pointer is really a predecessor.
|
|
+ * @return true if the left pointer is a predecessor.
|
|
+ */
|
|
+ boolean pred() {
|
|
+ return ( info & PRED_MASK ) != 0;
|
|
+ }
|
|
+ /** Checks whether the right pointer is really a successor.
|
|
+ * @return true if the right pointer is a successor.
|
|
+ */
|
|
+ boolean succ() {
|
|
+ return ( info & SUCC_MASK ) != 0;
|
|
+ }
|
|
+ /** Sets whether the left pointer is really a predecessor.
|
|
+ * @param pred if true then the left pointer will be considered a predecessor.
|
|
+ */
|
|
+ void pred( final boolean pred ) {
|
|
+ if ( pred ) info |= PRED_MASK;
|
|
+ else info &= ~PRED_MASK;
|
|
+ }
|
|
+ /** Sets whether the right pointer is really a successor.
|
|
+ * @param succ if true then the right pointer will be considered a successor.
|
|
+ */
|
|
+ void succ( final boolean succ ) {
|
|
+ if ( succ ) info |= SUCC_MASK;
|
|
+ else info &= ~SUCC_MASK;
|
|
+ }
|
|
+ /** Sets the left pointer to a predecessor.
|
|
+ * @param pred the predecessr.
|
|
+ */
|
|
+ void pred( final Entry <V> pred ) {
|
|
+ info |= PRED_MASK;
|
|
+ left = pred;
|
|
+ }
|
|
+ /** Sets the right pointer to a successor.
|
|
+ * @param succ the successor.
|
|
+ */
|
|
+ void succ( final Entry <V> succ ) {
|
|
+ info |= SUCC_MASK;
|
|
+ right = succ;
|
|
+ }
|
|
+ /** Sets the left pointer to the given subtree.
|
|
+ * @param left the new left subtree.
|
|
+ */
|
|
+ void left( final Entry <V> left ) {
|
|
+ info &= ~PRED_MASK;
|
|
+ this.left = left;
|
|
+ }
|
|
+ /** Sets the right pointer to the given subtree.
|
|
+ * @param right the new right subtree.
|
|
+ */
|
|
+ void right( final Entry <V> right ) {
|
|
+ info &= ~SUCC_MASK;
|
|
+ this.right = right;
|
|
+ }
|
|
+ /** Returns whether this node is black.
|
|
+ * @return true iff this node is black.
|
|
+ */
|
|
+ boolean black() {
|
|
+ return ( info & BLACK_MASK ) != 0;
|
|
+ }
|
|
+ /** Sets whether this node is black.
|
|
+ * @param black if true, then this node becomes black; otherwise, it becomes red..
|
|
+ */
|
|
+ void black( final boolean black ) {
|
|
+ if ( black ) info |= BLACK_MASK;
|
|
+ else info &= ~BLACK_MASK;
|
|
+ }
|
|
+ /** Computes the next entry in the set order.
|
|
+ *
|
|
+ * @return the next entry (<code>null</code>) if this is the last entry).
|
|
+ */
|
|
+ Entry <V> next() {
|
|
+ Entry <V> next = this.right;
|
|
+ if ( ( info & SUCC_MASK ) == 0 ) while ( ( next.info & PRED_MASK ) == 0 ) next = next.left;
|
|
+ return next;
|
|
+ }
|
|
+ /** Computes the previous entry in the set order.
|
|
+ *
|
|
+ * @return the previous entry (<code>null</code>) if this is the first entry).
|
|
+ */
|
|
+ Entry <V> prev() {
|
|
+ Entry <V> prev = this.left;
|
|
+ if ( ( info & PRED_MASK ) == 0 ) while ( ( prev.info & SUCC_MASK ) == 0 ) prev = prev.right;
|
|
+ return prev;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue(final V value) {
|
|
+ final V oldValue = this.value;
|
|
+ this.value = value;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> clone() {
|
|
+ Entry <V> c;
|
|
+ try {
|
|
+ c = (Entry <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key;
|
|
+ c.value = value;
|
|
+ c.info = info;
|
|
+ return c;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry <Integer, V> e = (Map.Entry <Integer, V>)o;
|
|
+ return ( (key) == (((e.getKey()).intValue())) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "=>" + value;
|
|
+ }
|
|
+ /*
|
|
+ public void prettyPrint() {
|
|
+ prettyPrint(0);
|
|
+ }
|
|
+
|
|
+ public void prettyPrint(int level) {
|
|
+ if ( pred() ) {
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println("pred: " + left );
|
|
+ }
|
|
+ else if (left != null)
|
|
+ left.prettyPrint(level +1 );
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println(key + "=" + value + " (" + balance() + ")");
|
|
+ if ( succ() ) {
|
|
+ for (int i = 0; i < level; i++)
|
|
+ System.err.print(" ");
|
|
+ System.err.println("succ: " + right );
|
|
+ }
|
|
+ else if (right != null)
|
|
+ right.prettyPrint(level + 1);
|
|
+ }*/
|
|
+ }
|
|
+ /*
|
|
+ public void prettyPrint() {
|
|
+ System.err.println("size: " + count);
|
|
+ if (tree != null) tree.prettyPrint();
|
|
+ }*/
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return findKey( k ) != null;
|
|
+ }
|
|
+ public int size() {
|
|
+ return count;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return count == 0;
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ final Entry <V> e = findKey( k );
|
|
+ return e == null ? defRetValue : e.value;
|
|
+ }
|
|
+ public int firstIntKey() {
|
|
+ if ( tree == null ) throw new NoSuchElementException();
|
|
+ return firstEntry.key;
|
|
+ }
|
|
+ public int lastIntKey() {
|
|
+ if ( tree == null ) throw new NoSuchElementException();
|
|
+ return lastEntry.key;
|
|
+ }
|
|
+ /** An abstract iterator on the whole range.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a threaded tree.
|
|
+ */
|
|
+ private class TreeIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ Entry <V> prev;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ Entry <V> next;
|
|
+ /** The last entry that was returned (or <code>null</code> if we did not iterate or used {@link #remove()}). */
|
|
+ Entry <V> curr;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this {@link TreeIterator} has been created using the nonempty constructor.*/
|
|
+ int index = 0;
|
|
+ TreeIterator() {
|
|
+ next = firstEntry;
|
|
+ }
|
|
+ TreeIterator( final int k ) {
|
|
+ if ( ( next = locateKey( k ) ) != null ) {
|
|
+ if ( compare( next.key, k ) <= 0 ) {
|
|
+ prev = next;
|
|
+ next = next.next();
|
|
+ }
|
|
+ else prev = next.prev();
|
|
+ }
|
|
+ }
|
|
+ public boolean hasNext() { return next != null; }
|
|
+ public boolean hasPrevious() { return prev != null; }
|
|
+ void updateNext() {
|
|
+ next = next.next();
|
|
+ }
|
|
+ Entry <V> nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = prev = next;
|
|
+ index++;
|
|
+ updateNext();
|
|
+ return curr;
|
|
+ }
|
|
+ void updatePrevious() {
|
|
+ prev = prev.prev();
|
|
+ }
|
|
+ Entry <V> previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = next = prev;
|
|
+ index--;
|
|
+ updatePrevious();
|
|
+ return curr;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == null ) throw new IllegalStateException();
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ if ( curr == prev ) index--;
|
|
+ next = prev = curr;
|
|
+ updatePrevious();
|
|
+ updateNext();
|
|
+ Int2ObjectRBTreeMap.this.remove( curr.key );
|
|
+ curr = null;
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ /** An iterator on the whole range.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a threaded tree.
|
|
+ */
|
|
+ private class EntryIterator extends TreeIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ EntryIterator() {}
|
|
+ EntryIterator( final int k ) {
|
|
+ super( k );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
|
|
+ final Comparator<? super Int2ObjectMap.Entry <V> > comparator = new Comparator<Int2ObjectMap.Entry <V> > () {
|
|
+ public int compare( final Int2ObjectMap.Entry <V> x, Int2ObjectMap.Entry <V> y ) {
|
|
+ return Int2ObjectRBTreeMap.this.actualComparator.compare( x.getIntKey(), y.getIntKey() );
|
|
+ }
|
|
+ };
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() {
|
|
+ return comparator;
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ return e.equals( f );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ if ( f != null ) Int2ObjectRBTreeMap.this.remove( f.key );
|
|
+ return f != null;
|
|
+ }
|
|
+ public int size() { return count; }
|
|
+ public void clear() { Int2ObjectRBTreeMap.this.clear(); }
|
|
+ public Int2ObjectMap.Entry <V> first() { return firstEntry; }
|
|
+ public Int2ObjectMap.Entry <V> last() { return lastEntry; }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ };
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on the whole range of keys.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the keys of a threaded tree. We
|
|
+ * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
|
|
+ * their type-specific counterparts) so that they return keys instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends TreeIterator implements IntListIterator {
|
|
+ public KeyIterator() {}
|
|
+ public KeyIterator( final int k ) { super( k ); }
|
|
+ public int nextInt() { return nextEntry().key; }
|
|
+ public int previousInt() { return previousEntry().key; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer next() { return (Integer.valueOf(nextEntry().key)); }
|
|
+ public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** A keyset implementation using a more direct implementation for iterators. */
|
|
+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
|
|
+ public IntBidirectionalIterator iterator() { return new KeyIterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new KeyIterator( from ); }
|
|
+ }
|
|
+ /** Returns a type-specific sorted set view of the keys contained in this map.
|
|
+ *
|
|
+ * <P>In addition to the semantics of {@link java.util.Map#keySet()}, you can
|
|
+ * safely cast the set returned by this call to a type-specific sorted
|
|
+ * set interface.
|
|
+ *
|
|
+ * @return a type-specific sorted set view of the keys contained in this map.
|
|
+ */
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on the whole range of values.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the values of a threaded tree. We
|
|
+ * simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly
|
|
+ * their type-specific counterparts) so that they return values instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends TreeIterator implements ObjectListIterator <V> {
|
|
+ public V next() { return nextEntry().value; }
|
|
+ public V previous() { return previousEntry().value; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>In addition to the semantics of {@link java.util.Map#values()}, you can
|
|
+ * safely cast the collection returned by this call to a type-specific collection
|
|
+ * interface.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return containsValue( k );
|
|
+ }
|
|
+ public int size() {
|
|
+ return count;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectRBTreeMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ public IntComparator comparator() {
|
|
+ return actualComparator;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> headMap( int to ) {
|
|
+ return new Submap( (0), true, to, false );
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> tailMap( int from ) {
|
|
+ return new Submap( from, false, (0), true );
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
|
|
+ return new Submap( from, false, to, false );
|
|
+ }
|
|
+ /** A submap with given range.
|
|
+ *
|
|
+ * <P>This class represents a submap. One has to specify the left/right
|
|
+ * limits (which can be set to -∞ 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 <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The start of the submap range, unless {@link #bottom} is true. */
|
|
+ int from;
|
|
+ /** The end of the submap range, unless {@link #top} is true. */
|
|
+ int to;
|
|
+ /** If true, the submap range starts from -∞. */
|
|
+ boolean bottom;
|
|
+ /** If true, the submap range goes to ∞. */
|
|
+ boolean top;
|
|
+ /** Cached set of entries. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ @SuppressWarnings("hiding")
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new submap with given key range.
|
|
+ *
|
|
+ * @param from the start of the submap range.
|
|
+ * @param bottom if true, the first parameter is ignored and the range starts from -∞.
|
|
+ * @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<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new AbstractObjectSortedSet<Int2ObjectMap.Entry <V> >() {
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new SubmapEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new SubmapEntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return Int2ObjectRBTreeMap.this.int2ObjectEntrySet().comparator(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ final Int2ObjectRBTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ return f != null && in( f.key ) && e.equals( f );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ final Int2ObjectRBTreeMap.Entry <V> f = findKey( ((e.getKey()).intValue()) );
|
|
+ if ( f != null && in( f.key ) ) Submap.this.remove( f.key );
|
|
+ return f != null;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ for( Iterator<?> i = iterator(); i.hasNext(); i.next() ) c++;
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return ! new SubmapIterator().hasNext(); }
|
|
+ public void clear() { Submap.this.clear(); }
|
|
+ public Int2ObjectMap.Entry <V> first() { return firstEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> last() { return lastEntry(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> from, Int2ObjectMap.Entry <V> to ) { return subMap( from.getIntKey(), to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> to ) { return headMap( to.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> from ) { return tailMap( from.getIntKey() ).int2ObjectEntrySet(); }
|
|
+ };
|
|
+ return entries;
|
|
+ }
|
|
+ private class KeySet extends AbstractInt2ObjectSortedMap <V>.KeySet {
|
|
+ public IntBidirectionalIterator iterator() { return new SubmapKeyIterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new SubmapKeyIterator( from ); }
|
|
+ }
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new SubmapValueIterator();
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return containsValue( k );
|
|
+ }
|
|
+ public int size() {
|
|
+ return Submap.this.size();
|
|
+ }
|
|
+ public void clear() {
|
|
+ Submap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return in( k ) && Int2ObjectRBTreeMap.this.containsKey( k );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final SubmapIterator i = new SubmapIterator();
|
|
+ Object ev;
|
|
+ while( i.hasNext() ) {
|
|
+ ev = i.nextEntry().value;
|
|
+ if ( ( (ev) == null ? (v) == null : (ev).equals(v) ) ) return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ public V get(final int k) {
|
|
+ final Int2ObjectRBTreeMap.Entry <V> e;
|
|
+ final int kk = k;
|
|
+ return in( kk ) && ( e = findKey( kk ) ) != null ? e.value : this.defRetValue;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ modified = false;
|
|
+ if ( ! in( k ) ) throw new IllegalArgumentException( "Key (" + k + ") out of range [" + ( bottom ? "-" : String.valueOf( from ) ) + ", " + ( top ? "-" : String.valueOf( to ) ) + ")" );
|
|
+ final V oldValue = Int2ObjectRBTreeMap.this.put( k, v );
|
|
+ return modified ? this.defRetValue : oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V oldValue = put( ((ok).intValue()), (ov) );
|
|
+ return modified ? (this.defRetValue) : (oldValue);
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ modified = false;
|
|
+ if ( ! in( k ) ) return this.defRetValue;
|
|
+ final V oldValue = Int2ObjectRBTreeMap.this.remove( k );
|
|
+ return modified ? oldValue : this.defRetValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object ok ) {
|
|
+ final V oldValue = remove( ((((Integer)(ok)).intValue())) );
|
|
+ return modified ? (oldValue) : (this.defRetValue);
|
|
+ }
|
|
+ public int size() {
|
|
+ final SubmapIterator i = new SubmapIterator();
|
|
+ int n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ n++;
|
|
+ i.nextEntry();
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return ! new SubmapIterator().hasNext();
|
|
+ }
|
|
+ public IntComparator comparator() {
|
|
+ return actualComparator;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) {
|
|
+ if ( top ) return new Submap( from, bottom, to, false );
|
|
+ return compare( to, this.to ) < 0 ? new Submap( from, bottom, to, false ) : this;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) {
|
|
+ if ( bottom ) return new Submap( from, false, to, top );
|
|
+ return compare( from, this.from ) > 0 ? new Submap( from, false, to, top ) : this;
|
|
+ }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) {
|
|
+ if ( top && bottom ) return new Submap( from, false, to, false );
|
|
+ if ( ! top ) to = compare( to, this.to ) < 0 ? to : this.to;
|
|
+ if ( ! bottom ) from = compare( from, this.from ) > 0 ? from : this.from;
|
|
+ if ( ! top && ! bottom && from == this.from && to == this.to ) return this;
|
|
+ return new Submap( from, false, to, false );
|
|
+ }
|
|
+ /** Locates the first entry.
|
|
+ *
|
|
+ * @return the first entry of this submap, or <code>null</code> if the submap is empty.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap.Entry <V> firstEntry() {
|
|
+ if ( tree == null ) return null;
|
|
+ // If this submap goes to -infinity, we return the main map first entry; otherwise, we locate the start of the map.
|
|
+ Int2ObjectRBTreeMap.Entry <V> e;
|
|
+ if ( bottom ) e = firstEntry;
|
|
+ else {
|
|
+ e = locateKey( from );
|
|
+ // If we find either the start or something greater we're OK.
|
|
+ if ( compare( e.key, from ) < 0 ) e = e.next();
|
|
+ }
|
|
+ // Finally, if this submap doesn't go to infinity, we check that the resulting key isn't greater than the end.
|
|
+ if ( e == null || ! top && compare( e.key, to ) >= 0 ) return null;
|
|
+ return e;
|
|
+ }
|
|
+ /** Locates the last entry.
|
|
+ *
|
|
+ * @return the last entry of this submap, or <code>null</code> if the submap is empty.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap.Entry <V> lastEntry() {
|
|
+ if ( tree == null ) return null;
|
|
+ // If this submap goes to infinity, we return the main map last entry; otherwise, we locate the end of the map.
|
|
+ Int2ObjectRBTreeMap.Entry <V> e;
|
|
+ if ( top ) e = lastEntry;
|
|
+ else {
|
|
+ e = locateKey( to );
|
|
+ // If we find something smaller than the end we're OK.
|
|
+ if ( compare( e.key, to ) >= 0 ) e = e.prev();
|
|
+ }
|
|
+ // Finally, if this submap doesn't go to -infinity, we check that the resulting key isn't smaller than the start.
|
|
+ if ( e == null || ! bottom && compare( e.key, from ) < 0 ) return null;
|
|
+ return e;
|
|
+ }
|
|
+ public int firstIntKey() {
|
|
+ Int2ObjectRBTreeMap.Entry <V> e = firstEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.key;
|
|
+ }
|
|
+ public int lastIntKey() {
|
|
+ Int2ObjectRBTreeMap.Entry <V> e = lastEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.key;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer firstKey() {
|
|
+ Int2ObjectRBTreeMap.Entry <V> e = firstEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.getKey();
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer lastKey() {
|
|
+ Int2ObjectRBTreeMap.Entry <V> e = lastEntry();
|
|
+ if ( e == null ) throw new NoSuchElementException();
|
|
+ return e.getKey();
|
|
+ }
|
|
+ /** An iterator for subranges.
|
|
+ *
|
|
+ * <P>This class inherits from {@link TreeIterator}, but overrides the methods that
|
|
+ * update the pointer after a {@link java.util.ListIterator#next()} or {@link java.util.ListIterator#previous()}. If we would
|
|
+ * move out of the range of the submap we just overwrite the next or previous
|
|
+ * entry with <code>null</code>.
|
|
+ */
|
|
+ private class SubmapIterator extends TreeIterator {
|
|
+ SubmapIterator() {
|
|
+ next = firstEntry();
|
|
+ }
|
|
+ SubmapIterator( final int k ) {
|
|
+ this();
|
|
+ if ( next != null ) {
|
|
+ if ( ! bottom && compare( k, next.key ) < 0 ) prev = null;
|
|
+ else if ( ! top && compare( k, ( prev = lastEntry() ).key ) >= 0 ) next = null;
|
|
+ else {
|
|
+ next = locateKey( k );
|
|
+ if ( compare( next.key, k ) <= 0 ) {
|
|
+ prev = next;
|
|
+ next = next.next();
|
|
+ }
|
|
+ else prev = next.prev();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ void updatePrevious() {
|
|
+ prev = prev.prev();
|
|
+ if ( ! bottom && prev != null && Int2ObjectRBTreeMap.this.compare( prev.key, from ) < 0 ) prev = null;
|
|
+ }
|
|
+ void updateNext() {
|
|
+ next = next.next();
|
|
+ if ( ! top && next != null && Int2ObjectRBTreeMap.this.compare( next.key, to ) >= 0 ) next = null;
|
|
+ }
|
|
+ }
|
|
+ private class SubmapEntryIterator extends SubmapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ SubmapEntryIterator() {}
|
|
+ SubmapEntryIterator( final int k ) {
|
|
+ super( k );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> next() { return nextEntry(); }
|
|
+ public Int2ObjectMap.Entry <V> previous() { return previousEntry(); }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** An iterator on a subrange of keys.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on a subrange of the
|
|
+ * keys of a threaded tree. We simply override the {@link
|
|
+ * java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
|
|
+ * type-specific counterparts) so that they return keys instead of
|
|
+ * entries.
|
|
+ */
|
|
+ private final class SubmapKeyIterator extends SubmapIterator implements IntListIterator {
|
|
+ public SubmapKeyIterator() { super(); }
|
|
+ public SubmapKeyIterator( int from ) { super( from ); }
|
|
+ public int nextInt() { return nextEntry().key; }
|
|
+ public int previousInt() { return previousEntry().key; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer next() { return (Integer.valueOf(nextEntry().key)); }
|
|
+ public Integer previous() { return (Integer.valueOf(previousEntry().key)); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ /** An iterator on a subrange of values.
|
|
+ *
|
|
+ * <P>This class can iterate in both directions on the values of a
|
|
+ * subrange of the keys of a threaded tree. We simply override the
|
|
+ * {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods (and possibly their
|
|
+ * type-specific counterparts) so that they return values instead of
|
|
+ * entries.
|
|
+ */
|
|
+ private final class SubmapValueIterator extends SubmapIterator implements ObjectListIterator <V> {
|
|
+ public V next() { return nextEntry().value; }
|
|
+ public V previous() { return previousEntry().value; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a deep copy of this tree map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this tree map; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this tree map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectRBTreeMap <V> clone() {
|
|
+ Int2ObjectRBTreeMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectRBTreeMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.allocatePaths();
|
|
+ if ( count != 0 ) {
|
|
+ // Also this apparently unfathomable code is derived from GNU libavl.
|
|
+ Entry <V> e, p, q, rp = new Entry <V>(), rq = new Entry <V>();
|
|
+ p = rp;
|
|
+ rp.left( tree );
|
|
+ q = rq;
|
|
+ rq.pred( null );
|
|
+ while( true ) {
|
|
+ if ( ! p.pred() ) {
|
|
+ e = p.left.clone();
|
|
+ e.pred( q.left );
|
|
+ e.succ( q );
|
|
+ q.left( e );
|
|
+ p = p.left;
|
|
+ q = q.left;
|
|
+ }
|
|
+ else {
|
|
+ while( p.succ() ) {
|
|
+ p = p.right;
|
|
+ if ( p == null ) {
|
|
+ q.right = null;
|
|
+ c.tree = rq.left;
|
|
+ c.firstEntry = c.tree;
|
|
+ while( c.firstEntry.left != null ) c.firstEntry = c.firstEntry.left;
|
|
+ c.lastEntry = c.tree;
|
|
+ while( c.lastEntry.right != null ) c.lastEntry = c.lastEntry.right;
|
|
+ return c;
|
|
+ }
|
|
+ q = q.right;
|
|
+ }
|
|
+ p = p.right;
|
|
+ q = q.right;
|
|
+ }
|
|
+ if ( ! p.succ() ) {
|
|
+ e = p.right.clone();
|
|
+ e.succ( q.right );
|
|
+ e.pred( q );
|
|
+ q.right( e );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ int n = count;
|
|
+ EntryIterator i = new EntryIterator();
|
|
+ Entry <V> e;
|
|
+ s.defaultWriteObject();
|
|
+ while(n-- != 0) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( e.key );
|
|
+ s.writeObject( e.value );
|
|
+ }
|
|
+ }
|
|
+ /** Reads the given number of entries from the input stream, returning the corresponding tree.
|
|
+ *
|
|
+ * @param s the input stream.
|
|
+ * @param n the (positive) number of entries to read.
|
|
+ * @param pred the entry containing the key that preceeds the first key in the tree.
|
|
+ * @param succ the entry containing the key that follows the last key in the tree.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private Entry <V> readTree( final java.io.ObjectInputStream s, final int n, final Entry <V> pred, final Entry <V> succ ) throws java.io.IOException, ClassNotFoundException {
|
|
+ if ( n == 1 ) {
|
|
+ final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
|
|
+ top.pred( pred );
|
|
+ top.succ( succ );
|
|
+ top.black( true );
|
|
+ return top;
|
|
+ }
|
|
+ if ( n == 2 ) {
|
|
+ /* We handle separately this case so that recursion will
|
|
+ *always* be on nonempty subtrees. */
|
|
+ final Entry <V> top = new Entry <V>( s.readInt(), (V) s.readObject() );
|
|
+ top.black( true );
|
|
+ top.right( new Entry <V>( s.readInt(), (V) s.readObject() ) );
|
|
+ top.right.pred( top );
|
|
+ top.pred( pred );
|
|
+ top.right.succ( succ );
|
|
+ return top;
|
|
+ }
|
|
+ // The right subtree is the largest one.
|
|
+ final int rightN = n / 2, leftN = n - rightN - 1;
|
|
+ final Entry <V> top = new Entry <V>();
|
|
+ top.left( readTree( s, leftN, pred, top ) );
|
|
+ top.key = s.readInt();
|
|
+ top.value = (V) s.readObject();
|
|
+ top.black( true );
|
|
+ top.right( readTree( s, rightN, top, succ ) );
|
|
+ if ( n + 2 == ( ( n + 2 ) & -( n + 2 ) ) ) top.right.black( false ); // Quick test for determining whether n + 2 is a power of 2.
|
|
+ return top;
|
|
+ }
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ /* The storedComparator is now correctly set, but we must restore
|
|
+ on-the-fly the actualComparator. */
|
|
+ setActualComparator();
|
|
+ allocatePaths();
|
|
+ if ( count != 0 ) {
|
|
+ tree = readTree( s, count, null, null );
|
|
+ Entry <V> e;
|
|
+ e = tree;
|
|
+ while( e.left() != null ) e = e.left();
|
|
+ firstEntry = e;
|
|
+ e = tree;
|
|
+ while( e.right() != null ) e = e.right();
|
|
+ lastEntry = e;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTree( tree, 0, -1 );
|
|
+ }
|
|
+ private void checkNodePath() {}
|
|
+ @SuppressWarnings("unused")
|
|
+ private static <V> int checkTree( Entry <V> e, int d, int D ) { return 0; }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000..04fbc68
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
|
|
@@ -0,0 +1,181 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()}, {@link #values()},
|
|
+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap
|
|
+ */
|
|
+public interface Int2ObjectSortedMap <V> extends Int2ObjectMap <V>, SortedMap<Integer, V> {
|
|
+ /** A sorted entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of entry objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Int2ObjectMap.Entry <V> >, FastEntrySet <V> {
|
|
+ /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ */
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( Int2ObjectMap.Entry <V> from );
|
|
+ }
|
|
+ /** Returns a sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Map.Entry<Integer, V>> entrySet();
|
|
+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
|
|
+ /** Returns a sorted-set view of the keys contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ IntSortedSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link SortedMap}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
|
|
+ *
|
|
+ * @see SortedMap#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> subMap(Integer fromKey, Integer toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> headMap(Integer toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> tailMap(Integer fromKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> subMap(int fromKey, int toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> headMap(int toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> tailMap(int fromKey);
|
|
+ /**
|
|
+ * @see SortedMap#firstKey()
|
|
+ */
|
|
+ int firstIntKey();
|
|
+ /**
|
|
+ * @see SortedMap#lastKey()
|
|
+ */
|
|
+ int lastIntKey();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
|
|
new file mode 100644
|
|
index 0000000..49e4cc7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
|
|
@@ -0,0 +1,326 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
|
|
+import java.util.Comparator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectSortedMaps {
|
|
+ private Int2ObjectSortedMaps() {}
|
|
+ /** Returns a comparator for entries based on a given comparator on keys.
|
|
+ *
|
|
+ * @param comparator a comparator on keys.
|
|
+ * @return the associated comparator on entries.
|
|
+ */
|
|
+ public static Comparator<? super Map.Entry<Integer, ?>> entryComparator( final IntComparator comparator ) {
|
|
+ return new Comparator<Map.Entry<Integer, ?>>() {
|
|
+ public int compare( Map.Entry<Integer, ?> x, Map.Entry<Integer, ?> y ) {
|
|
+ return comparator.compare( x.getKey(), y.getKey() );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class EmptySortedMap <V> extends Int2ObjectMaps.EmptyMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySortedMap() {}
|
|
+ public IntComparator comparator() { return null; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet keySet() { return IntSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { return EMPTY_MAP; }
|
|
+ public int firstIntKey() { throw new NoSuchElementException(); }
|
|
+ public int lastIntKey() { throw new NoSuchElementException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
|
|
+ }
|
|
+ /** An empty sorted map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
|
|
+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty sorted map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Int2ObjectSortedMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Int2ObjectMaps.Singleton <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntComparator comparator;
|
|
+ protected Singleton( final int key, final V value, IntComparator comparator ) {
|
|
+ super( key, value );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ this( key, value, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final int k1, final int k2 ) {
|
|
+ return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ public IntComparator comparator() { return comparator; }
|
|
+
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Int2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
|
|
+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.singleton( key, comparator ); return (IntSortedSet )keys; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
|
|
+ public int firstIntKey() { return key; }
|
|
+ public int lastIntKey() { return key; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> singleton( final Integer key, V value ) {
|
|
+ return new Singleton <V>( ((key).intValue()), (value) );
|
|
+ }
|
|
+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @param comparator the comparator to use in the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> singleton( final Integer key, V value, IntComparator comparator ) {
|
|
+ return new Singleton <V>( ((key).intValue()), (value), comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> singleton( final int key, final V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @param comparator the comparator to use in the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> singleton( final int key, final V value, IntComparator comparator ) {
|
|
+ return new Singleton <V>( key, value, comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted maps. */
|
|
+ public static class SynchronizedSortedMap <V> extends Int2ObjectMaps.SynchronizedMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectSortedMap <V> sortedMap;
|
|
+ protected SynchronizedSortedMap( final Int2ObjectSortedMap <V> m, final Object sync ) {
|
|
+ super( m, sync );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ protected SynchronizedSortedMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ super( m );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ public IntComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.int2ObjectEntrySet(), sync ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
|
|
+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.synchronize( sortedMap.keySet(), sync ); return (IntSortedSet )keys; }
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
|
|
+ public int firstIntKey() { synchronized( sync ) { return sortedMap.firstIntKey(); } }
|
|
+ public int lastIntKey() { synchronized( sync ) { return sortedMap.lastIntKey(); } }
|
|
+ public Integer firstKey() { synchronized( sync ) { return sortedMap.firstKey(); } }
|
|
+ public Integer lastKey() { synchronized( sync ) { return sortedMap.lastKey(); } }
|
|
+ public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
|
|
+ public Int2ObjectSortedMap <V> headMap( final Integer to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final Integer from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in a synchronized sorted map.
|
|
+ * @return a synchronized view of the specified sorted map.
|
|
+ * @see java.util.Collections#synchronizedSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> synchronize( final Int2ObjectSortedMap <V> m ) { return new SynchronizedSortedMap <V>( m ); }
|
|
+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in a synchronized sorted map.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted sorted map.
|
|
+ * @return a synchronized view of the specified sorted map.
|
|
+ * @see java.util.Collections#synchronizedSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> synchronize( final Int2ObjectSortedMap <V> m, final Object sync ) { return new SynchronizedSortedMap <V>( m, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted maps. */
|
|
+ public static class UnmodifiableSortedMap <V> extends Int2ObjectMaps.UnmodifiableMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Int2ObjectSortedMap <V> sortedMap;
|
|
+ protected UnmodifiableSortedMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ super( m );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ public IntComparator comparator() { return sortedMap.comparator(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.int2ObjectEntrySet() ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
|
|
+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.unmodifiable( sortedMap.keySet() ); return (IntSortedSet )keys; }
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
|
|
+ public int firstIntKey() { return sortedMap.firstIntKey(); }
|
|
+ public int lastIntKey() { return sortedMap.lastIntKey(); }
|
|
+ public Integer firstKey() { return sortedMap.firstKey(); }
|
|
+ public Integer lastKey() { return sortedMap.lastKey(); }
|
|
+ public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
|
|
+ public Int2ObjectSortedMap <V> headMap( final Integer to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
|
|
+ public Int2ObjectSortedMap <V> tailMap( final Integer from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted map backed by the given type-specific sorted map.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in an unmodifiable sorted map.
|
|
+ * @return an unmodifiable view of the specified sorted map.
|
|
+ * @see java.util.Collections#unmodifiableSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Int2ObjectSortedMap <V> unmodifiable( final Int2ObjectSortedMap <V> m ) { return new UnmodifiableSortedMap <V>( m ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
|
|
new file mode 100644
|
|
index 0000000..d6835e9
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
|
|
@@ -0,0 +1,226 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.io.Serializable;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based FIFO queue, supporting also deque operations.
|
|
+ *
|
|
+ * <P>Instances of this class represent a FIFO queue using a backing
|
|
+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
|
|
+ * to reduce its memory usage, if necessary.
|
|
+ *
|
|
+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
|
|
+ */
|
|
+public class IntArrayFIFOQueue extends AbstractIntPriorityQueue implements Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ /** The standard initial capacity of a queue. */
|
|
+ public final static int INITIAL_CAPACITY = 4;
|
|
+ /** The backing array. */
|
|
+ protected transient int array[];
|
|
+ /** The current (cached) length of {@link #array}. */
|
|
+ protected transient int length;
|
|
+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
|
|
+ protected transient int start;
|
|
+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
|
|
+ * Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
|
|
+ protected transient int end;
|
|
+ /** Creates a new empty queue with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+
|
|
+ public IntArrayFIFOQueue( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ array = new int[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
|
|
+ length = array.length;
|
|
+ }
|
|
+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
|
|
+ */
|
|
+ public IntArrayFIFOQueue() {
|
|
+ this( INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Returns <code>null</code> (FIFO queues have no comparator).
|
|
+ * @return <code>null</code>.
|
|
+ */
|
|
+ @Override
|
|
+ public IntComparator comparator() {
|
|
+ return null;
|
|
+ }
|
|
+ @Override
|
|
+ public int dequeueInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ final int t = array[ start ];
|
|
+ if ( ++start == length ) start = 0;
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+ /** Dequeues the last element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ public int dequeueLastInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ if ( end == 0 ) end = length;
|
|
+ final int t = array[ --end ];
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+
|
|
+ private final void resize( final int size, final int newLength ) {
|
|
+ final int[] newArray = new int[ newLength ];
|
|
+ if ( start >= end ) {
|
|
+ if ( size != 0 ) {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ }
|
|
+ else System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ start = 0;
|
|
+ end = size;
|
|
+ array = newArray;
|
|
+ length = newLength;
|
|
+ }
|
|
+ private final void expand() {
|
|
+ resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
|
|
+ }
|
|
+ private final void reduce() {
|
|
+ final int size = size();
|
|
+ if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
|
|
+ }
|
|
+ @Override
|
|
+ public void enqueue( int x ) {
|
|
+ array[ end++ ] = x;
|
|
+ if ( end == length ) end = 0;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
|
|
+ */
|
|
+ public void enqueueFirst( int x ) {
|
|
+ if ( start == 0 ) start = length;
|
|
+ array[ --start ] = x;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Returns the first element of the queue.
|
|
+ * @return the first element of the queue.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ start ];
|
|
+ }
|
|
+ /** Returns the last element of the queue.
|
|
+ * @return the last element of the queue.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ ( end == 0 ? length : end ) - 1 ];
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ start = end = 0;
|
|
+ }
|
|
+ /** Trims the queue to the smallest possible size. */
|
|
+
|
|
+ public void trim() {
|
|
+ final int size = size();
|
|
+ final int[] newArray =
|
|
+ new int[ size + 1 ];
|
|
+ if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ else {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ start = 0;
|
|
+ length = ( end = size ) + 1;
|
|
+ array = newArray;
|
|
+ }
|
|
+ @Override
|
|
+ public int size() {
|
|
+ final int apparentLength = end - start;
|
|
+ return apparentLength >= 0 ? apparentLength : length + apparentLength;
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ int size = size();
|
|
+ s.writeInt( size );
|
|
+ for( int i = start; size-- != 0; ) {
|
|
+ s.writeInt( array[ i++ ] );
|
|
+ if ( i == length ) i = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ end = s.readInt();
|
|
+ array = new int[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
|
|
+ for( int i = 0; i < end; i++ ) array[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..34bf5c0
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
|
|
@@ -0,0 +1,295 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based semi-indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use as reference list a <em>reference array</em>,
|
|
+ * which must be provided to each constructor, and represent a priority queue
|
|
+ * using a backing array of integer indices—all operations are performed
|
|
+ * directly on the array. The array is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small. Moreover, it allows to enqueue several
|
|
+ * time the same index, without limitations.
|
|
+ */
|
|
+public class IntArrayIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
|
|
+ /** The reference array. */
|
|
+ protected int refArray[];
|
|
+ /** The backing array. */
|
|
+ protected int array[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue without elements with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new int[ capacity ];
|
|
+ this.refArray = refArray;
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ /** Returns the index (in {@link #array}) of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ int first = refArray[ array[ firstIndex ] ];
|
|
+ if ( c == null ) while( i-- != 0 ) { if ( ( (refArray[ array[ i ] ]) < (first) ) ) first = refArray[ array[ firstIndex = i ] ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( refArray[ array[ i ] ], first ) < 0 ) first = refArray[ array[ firstIndex = i ] ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ /** Returns the index (in {@link #array}) of the largest element. */
|
|
+
|
|
+ private int findLast() {
|
|
+ int i = size;
|
|
+ int lastIndex = --i;
|
|
+ int last = refArray[ array[ lastIndex ] ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (last) < (refArray[ array[ i ] ]) ) ) last = refArray[ array[ lastIndex = i ] ]; }
|
|
+ else { while( i-- != 0 ) if ( c.compare( last, refArray[ array[ i ] ] ) < 0 ) last = refArray[ array[ lastIndex = i ] ]; }
|
|
+ return lastIndex;
|
|
+ }
|
|
+ protected final void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+ /** Ensures that the given index is a firstIndexValid reference.
|
|
+ *
|
|
+ * @param index an index in the reference array.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
|
|
+ */
|
|
+ protected void ensureElement( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
|
|
+ }
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
|
|
+ * when <code>x</code> is already in the queue. However, the queue state will become
|
|
+ * inconsistent and the following behaviour will not be predictable.
|
|
+ */
|
|
+
|
|
+ public void enqueue( int x ) {
|
|
+ ensureElement( x );
|
|
+ if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (refArray[ x ]) < (refArray[ array[ firstIndex ] ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( refArray[ x ], refArray[ array[ firstIndex ] ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ ensureNonEmpty();
|
|
+ final int firstIndex = findFirst();
|
|
+ final int result = array[ firstIndex ];
|
|
+ if ( --size != 0 ) System.arraycopy( array, firstIndex + 1, array, firstIndex, size - firstIndex );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public int first() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public int last() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findLast() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ *
|
|
+ * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
|
|
+ * when <code>index</code> is not in the queue.
|
|
+ */
|
|
+ public void changed( int index ) {
|
|
+ ensureElement( index );
|
|
+ if ( index == firstIndex ) firstIndexValid = false;
|
|
+ }
|
|
+ public void allChanged() {
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public boolean remove( int index ) {
|
|
+ ensureElement( index );
|
|
+ final int[] a = array;
|
|
+ int i = size;
|
|
+ while( i-- != 0 ) if ( a[ i ] == index ) break;
|
|
+ if ( i < 0 ) return false;
|
|
+ firstIndexValid = false;
|
|
+ if ( --size != 0 ) System.arraycopy( a, i + 1, a, i, size - i );
|
|
+ return true;
|
|
+ }
|
|
+ public int front( int[] a ) {
|
|
+ final int top = refArray[ array[ findFirst() ] ];
|
|
+ int i = size, c = 0;
|
|
+ while( i-- != 0 ) if ( ( (top) == (refArray[ array[ i ] ]) ) ) a[ c++ ] = array[ i ];
|
|
+ return c;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() { size = 0; firstIndexValid = false; }
|
|
+ /** Trims the backing array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = IntArrays.trim( array, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ public String toString() {
|
|
+ StringBuffer s = new StringBuffer();
|
|
+ s.append( "[" );
|
|
+ for ( int i = 0; i < size; i++ ) {
|
|
+ if ( i != 0 ) s.append( ", " );
|
|
+ s.append( refArray[ array [ i ] ] );
|
|
+ }
|
|
+ s.append( "]" );
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
|
|
new file mode 100644
|
|
index 0000000..ec18eae
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
|
|
@@ -0,0 +1,501 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling its current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible. The backing array is exposed by the
|
|
+ * {@link #elements()} method.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class IntArrayList extends AbstractIntList implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353130L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** The backing array. */
|
|
+ protected transient int a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected IntArrayList( final int a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+
|
|
+ public IntArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = new int[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public IntArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final Collection<? extends Integer> c ) {
|
|
+ this( c.size() );
|
|
+ size = IntIterators.unwrap( IntIterators.asIntIterator( c.iterator() ), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntCollection c ) {
|
|
+ this( c.size() );
|
|
+ size = IntIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntList l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final int a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public IntArrayList( final int a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final Iterator<? extends Integer> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntIterator i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.nextInt() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public int[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static IntArrayList wrap( final int a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final IntArrayList l = new IntArrayList ( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static IntArrayList wrap( final int a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ a = IntArrays.ensureCapacity( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ private void grow( final int capacity ) {
|
|
+ a = IntArrays.grow( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public int getInt( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final int k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final int k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int removeInt( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final int old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeInt( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public int set( final int index, final int k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ int old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final int t[] = new int[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final int[] a, final int offset, final int length ) {
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final int a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ public int[] toIntArray( int a[] ) {
|
|
+ if ( a == null || a.length < size ) a = new int[ size ];
|
|
+ System.arraycopy( this.a, 0, a, 0, size );
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( int index, final IntCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ final IntIterator i = c.iterator();
|
|
+ size += n;
|
|
+ while( n-- != 0 ) a[ index++ ] = i.nextInt();
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ ensureIndex( index );
|
|
+ final int n = l.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ l.getElements( 0, a, index, n );
|
|
+ size += n;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final IntCollection c ) {
|
|
+ final int[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final int[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( (Integer.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ IntArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntArrayList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public IntArrayList clone() {
|
|
+ IntArrayList c = new IntArrayList ( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final IntArrayList l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final int[] a1 = a;
|
|
+ final int[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final IntArrayList l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final int a1[] = a, a2[] = l.a;
|
|
+ int e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new int[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..dcf704d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
|
|
@@ -0,0 +1,229 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a backing
|
|
+ * array—all operations are performed directly on the array. The array is
|
|
+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
|
|
+ * to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small.
|
|
+ */
|
|
+public class IntArrayPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array. */
|
|
+
|
|
+ protected transient int array[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ transient protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ transient protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public IntArrayPriorityQueue( int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( IntComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, int size, final IntComparator c ) {
|
|
+ this( c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, final IntComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Returns the index of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ int first = array[ firstIndex ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ private void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+
|
|
+ public void enqueue( int x ) {
|
|
+ if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public int dequeueInt() {
|
|
+ ensureNonEmpty();
|
|
+ final int first = findFirst();
|
|
+ final int result = array[ first ];
|
|
+ System.arraycopy( array, first + 1, array, first, --size - first );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = IntArrays.trim( array, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( array.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( array[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ array = new int[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) array[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
|
|
new file mode 100644
|
|
index 0000000..af8014d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
|
|
@@ -0,0 +1,218 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class IntArraySet extends AbstractIntSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient int[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public IntArraySet( final int[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public IntArraySet() {
|
|
+ this.a = IntArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public IntArraySet( final int capacity ) {
|
|
+ this.a = new int[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public IntArraySet( IntCollection c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public IntArraySet( final Collection<? extends Integer> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public IntArraySet( final int[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final int o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ public IntIterator iterator() {
|
|
+ return new AbstractIntIterator () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final int k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final int k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final int[] b = new int[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntArraySet clone() {
|
|
+ IntArraySet c;
|
|
+ try {
|
|
+ c = (IntArraySet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new int[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
|
|
new file mode 100644
|
|
index 0000000..e9d8586
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
|
|
@@ -0,0 +1,2462 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import java.util.concurrent.Callable;
|
|
+import java.util.concurrent.ExecutorCompletionService;
|
|
+import java.util.concurrent.ExecutorService;
|
|
+import java.util.concurrent.Executors;
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
|
|
+ * contain several methods make it possible to load and save arrays of primitive types as sequences
|
|
+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
|
|
+ * to sort an array using the values in another array as comparator.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
|
|
+ * on random-looking data. In
|
|
+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
|
|
+ * exploits parallelism better.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class IntArrays {
|
|
+ private IntArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static int[] EMPTY_ARRAY = {};
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static int[] ensureCapacity( final int[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int t[] =
|
|
+ new int[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static int[] ensureCapacity( final int[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int t[] =
|
|
+ new int[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>array.length</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static int[] grow( final int[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final int t[] =
|
|
+ new int[ newLength ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length, preserving just a part of the array.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>preserve</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static int[] grow( final int[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final int t[] =
|
|
+ new int[ newLength ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Trims the given array to the given length.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new maximum length for the array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code>
|
|
+ * entries or less; otherwise, an array with
|
|
+ * <code>length</code> entries whose entries are the same as
|
|
+ * the first <code>length</code> entries of <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static int[] trim( final int[] array, final int length ) {
|
|
+ if ( length >= array.length ) return array;
|
|
+ final int t[] =
|
|
+ length == 0 ? EMPTY_ARRAY : new int[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, length );
|
|
+ return t;
|
|
+ }
|
|
+ /** Sets the length of the given array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new length for the array.
|
|
+ * @return <code>array</code>, if it contains exactly <code>length</code>
|
|
+ * entries; otherwise, if it contains <em>more</em> than
|
|
+ * <code>length</code> entries, an array with <code>length</code> entries
|
|
+ * whose entries are the same as the first <code>length</code> entries of
|
|
+ * <code>array</code>; otherwise, an array with <code>length</code> entries
|
|
+ * whose first <code>array.length</code> entries are the same as those of
|
|
+ * <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static int[] setLength( final int[] array, final int length ) {
|
|
+ if ( length == array.length ) return array;
|
|
+ if ( length < array.length ) return trim( array, length );
|
|
+ return ensureCapacity( array, length );
|
|
+ }
|
|
+ /** Returns a copy of a portion of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param offset the first element to copy.
|
|
+ * @param length the number of elements to copy.
|
|
+ * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static int[] copy( final int[] array, final int offset, final int length ) {
|
|
+ ensureOffsetLength( array, offset, length );
|
|
+ final int[] a =
|
|
+ length == 0 ? EMPTY_ARRAY : new int[ length ];
|
|
+ System.arraycopy( array, offset, a, 0, length );
|
|
+ return a;
|
|
+ }
|
|
+ /** Returns a copy of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @return a copy of <code>array</code>.
|
|
+ */
|
|
+ public static int[] copy( final int[] array ) {
|
|
+ return array.clone();
|
|
+ }
|
|
+ /** Fills the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param value the new value for all elements of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static void fill( final int[] array, final int value ) {
|
|
+ int i = array.length;
|
|
+ while( i-- != 0 ) array[ i ] = value;
|
|
+ }
|
|
+ /** Fills a portion of the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param from the starting index of the portion to fill (inclusive).
|
|
+ * @param to the end index of the portion to fill (exclusive).
|
|
+ * @param value the new value for all elements of the specified portion of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static void fill( final int[] array, final int from, int to, final int value ) {
|
|
+ ensureFromTo( array, from, to );
|
|
+ if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
|
|
+ else for( int i = from; i < to; i++ ) array[ i ] = value;
|
|
+ }
|
|
+ /** Returns true if the two arrays are elementwise equal.
|
|
+ *
|
|
+ * @param a1 an array.
|
|
+ * @param a2 another array.
|
|
+ * @return true if the two arrays are of the same length, and their elements are equal.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static boolean equals( final int[] a1, final int a2[] ) {
|
|
+ int i = a1.length;
|
|
+ if ( i != a2.length ) return false;
|
|
+ while( i-- != 0 ) if (! ( (a1[ i ]) == (a2[ i ]) ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param from a start index (inclusive).
|
|
+ * @param to an end index (exclusive).
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
|
|
+ */
|
|
+ public static void ensureFromTo( final int[] a, final int from, final int to ) {
|
|
+ Arrays.ensureFromTo( a.length, from, to );
|
|
+ }
|
|
+ /** Ensures that a range given by an offset and a length fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param offset a start index.
|
|
+ * @param length a length (the number of elements in the range).
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
|
|
+ */
|
|
+ public static void ensureOffsetLength( final int[] a, final int offset, final int length ) {
|
|
+ Arrays.ensureOffsetLength( a.length, offset, length );
|
|
+ }
|
|
+ /** Ensures that two arrays are of the same length.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param b another array.
|
|
+ * @throws IllegalArgumentException if the two argument arrays are not of the same length.
|
|
+ */
|
|
+ public static void ensureSameLength( final int[] a, final int[] b ) {
|
|
+ if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
|
|
+ }
|
|
+ private static final int QUICKSORT_NO_REC = 16;
|
|
+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
|
|
+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
|
|
+ private static final int MERGESORT_NO_REC = 16;
|
|
+ /** Swaps two elements of an anrray.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ */
|
|
+ public static void swap( final int x[], final int a, final int b ) {
|
|
+ final int t = x[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ x[ b ] = t;
|
|
+ }
|
|
+ /** Swaps two sequences of elements of an array.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ * @param n the number of elements to exchange starting at {@code a} and {@code b}.
|
|
+ */
|
|
+ public static void swap( final int[] x, int a, int b, final int n ) {
|
|
+ for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
|
|
+ }
|
|
+ private static int med3( final int x[], final int a, final int b, final int c, IntComparator comp ) {
|
|
+ final int ab = comp.compare( x[ a ], x[ b ] );
|
|
+ final int ac = comp.compare( x[ a ], x[ c ] );
|
|
+ final int bc = comp.compare( x[ b ], x[ c ] );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static void selectionSort( final int[] a, final int from, final int to, final IntComparator comp ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final int u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ private static void insertionSort( final int[] a, final int from, final int to, final IntComparator comp ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final int[] x, final int from, final int to, final IntComparator comp ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s, comp );
|
|
+ m = med3( x, m - s, m, m + s, comp );
|
|
+ n = med3( x, n - 2 * s, n - s, n, comp );
|
|
+ }
|
|
+ m = med3( x, l, m, n, comp ); // Mid-size, med of 3
|
|
+ final int v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final int[] x, final IntComparator comp ) {
|
|
+ quickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortComp extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] x;
|
|
+ private final IntComparator comp;
|
|
+ public ForkJoinQuickSortComp( final int[] x , final int from , final int to, final IntComparator comp ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.comp = comp;
|
|
+ }
|
|
+ @Override
|
|
+ protected void compute() {
|
|
+ final int[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final int v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ), new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ) );
|
|
+ else invokeAll( new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x, final int from, final int to, final IntComparator comp ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortComp ( x, from, to, comp ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x, final IntComparator comp ) {
|
|
+ parallelQuickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+
|
|
+ private static int med3( final int x[], final int a, final int b, final int c ) {
|
|
+ final int ab = ( Integer.compare((x[ a ]),(x[ b ])) );
|
|
+ final int ac = ( Integer.compare((x[ a ]),(x[ c ])) );
|
|
+ final int bc = ( Integer.compare((x[ b ]),(x[ c ])) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static void selectionSort( final int[] a, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( ( (a[ j ]) < (a[ m ]) ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final int u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void insertionSort( final int[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = a[ j - 1 ]; ( (t) < (u) ); u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSort( final int[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, l, m, n ); // Mid-size, med of 3
|
|
+ final int v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Integer.compare((x[ b ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( Integer.compare((x[ c ]),(v)) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final int[] x ) {
|
|
+ quickSort( x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] x;
|
|
+ public ForkJoinQuickSort( final int[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final int[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final int v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Integer.compare((x[ b ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( Integer.compare((x[ c ]),(v)) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ), new ForkJoinQuickSort ( x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort ( x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort ( x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x ) {
|
|
+ parallelQuickSort( x, 0, x.length );
|
|
+ }
|
|
+
|
|
+ private static int med3Indirect( final int perm[], final int x[], final int a, final int b, final int c ) {
|
|
+ final int aa = x[ perm[ a ] ];
|
|
+ final int bb = x[ perm[ b ] ];
|
|
+ final int cc = x[ perm[ c ] ];
|
|
+ final int ab = ( Integer.compare((aa),(bb)) );
|
|
+ final int ac = ( Integer.compare((aa),(cc)) );
|
|
+ final int bc = ( Integer.compare((bb),(cc)) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static void insertionSortIndirect( final int[] perm, final int[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = perm[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ); u = perm[ --j - 1 ] ) {
|
|
+ perm[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ perm[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSortIndirect( final int[] perm, final int[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
|
|
+ final int v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Integer.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( Integer.compare((x[ perm[ c ] ]),(v)) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ */
|
|
+ public static void quickSortIndirect( final int perm[], final int[] x ) {
|
|
+ quickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortIndirect extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] perm;
|
|
+ private final int[] x;
|
|
+ public ForkJoinQuickSortIndirect( final int perm[], final int[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.perm = perm;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final int[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ m = med3Indirect( perm, x, l, m, n );
|
|
+ final int v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Integer.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( Integer.compare((x[ perm[ c ] ]),(v)) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ), new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSortIndirect( final int[] perm, final int[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortIndirect ( perm, x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void parallelQuickSortIndirect( final int perm[], final int[] x ) {
|
|
+ parallelQuickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ * @param from the index of the first element (inclusive) to be stabilized.
|
|
+ * @param to the index of the last element (exclusive) to be stabilized.
|
|
+ */
|
|
+ public static void stabilize( final int perm[], final int[] x, final int from, final int to ) {
|
|
+ int curr = from;
|
|
+ for( int i = from + 1; i < to; i++ ) {
|
|
+ if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
|
|
+ if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
|
|
+ curr = i;
|
|
+ }
|
|
+ }
|
|
+ if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ */
|
|
+ public static void stabilize( final int perm[], final int[] x ) {
|
|
+ stabilize( perm, x, 0, perm.length );
|
|
+ }
|
|
+
|
|
+ private static int med3( final int x[], final int[] y, final int a, final int b, final int c ) {
|
|
+ int t;
|
|
+ final int ab = ( t = ( Integer.compare((x[ a ]),(x[ b ])) ) ) == 0 ? ( Integer.compare((y[ a ]),(y[ b ])) ) : t;
|
|
+ final int ac = ( t = ( Integer.compare((x[ a ]),(x[ c ])) ) ) == 0 ? ( Integer.compare((y[ a ]),(y[ c ])) ) : t;
|
|
+ final int bc = ( t = ( Integer.compare((x[ b ]),(x[ c ])) ) ) == 0 ? ( Integer.compare((y[ b ]),(y[ c ])) ) : t;
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static void swap( final int x[], final int[] y, final int a, final int b ) {
|
|
+ final int t = x[ a ];
|
|
+ final int u = y[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ y[ a ] = y[ b ];
|
|
+ x[ b ] = t;
|
|
+ y[ b ] = u;
|
|
+ }
|
|
+ private static void swap( final int[] x, final int[] y, int a, int b, final int n ) {
|
|
+ for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
|
|
+ }
|
|
+
|
|
+ private static void selectionSort( final int[] a, final int[] b, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i, u;
|
|
+ for( int j = i + 1; j < to; j++ )
|
|
+ if ( ( u = ( Integer.compare((a[ j ]),(a[ m ])) ) ) < 0 || u == 0 && ( (b[ j ]) < (b[ m ]) ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ int t = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = t;
|
|
+ t = b[ i ];
|
|
+ b[ i ] = b[ m ];
|
|
+ b[ m ] = t;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSort( final int[] x, final int[] y, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, y, l, m, n ); // Mid-size, med of 3
|
|
+ final int v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( Integer.compare((x[ b ]),(v)) ) ) == 0 ? ( Integer.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( Integer.compare((x[ c ]),(v)) ) ) == 0 ? ( Integer.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static void quickSort( final int[] x, final int[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ quickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort2 extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] x, y;
|
|
+ public ForkJoinQuickSort2( final int[] x, final int[] y, final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.y = y;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final int[] x = this.x;
|
|
+ final int[] y = this.y;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ m = med3( x, y, l, m, n );
|
|
+ final int v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( Integer.compare((x[ b ]),(v)) ) ) == 0 ? ( Integer.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( Integer.compare((x[ c ]),(v)) ) ) == 0 ? ( Integer.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ), new ForkJoinQuickSort2 ( x, y, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort2 ( x, y, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x, final int[] y, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort2 ( x, y, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final int[] x, final int[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ parallelQuickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+
|
|
+ public static void mergeSort( final int a[], final int from, final int to, final int supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, a );
|
|
+ mergeSort( supp, mid, to, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( ( (supp[ mid - 1 ]) <= (supp[ mid ]) ) ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && ( (supp[ p ]) <= (supp[ q ]) ) ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void mergeSort( final int a[], final int from, final int to ) {
|
|
+ mergeSort( a, from, to, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void mergeSort( final int a[] ) {
|
|
+ mergeSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+ public static void mergeSort( final int a[], final int from, final int to, IntComparator comp, final int supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, comp, a );
|
|
+ mergeSort( supp, mid, to, comp, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void mergeSort( final int a[], final int from, final int to, IntComparator comp ) {
|
|
+ mergeSort( a, from, to, comp, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void mergeSort( final int a[], IntComparator comp ) {
|
|
+ mergeSort( a, 0, a.length, comp );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+
|
|
+ public static int binarySearch( final int[] a, int from, int to, final int key ) {
|
|
+ int midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ if (midVal < key) from = mid + 1;
|
|
+ else if (midVal > key) to = mid - 1;
|
|
+ else return mid;
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final int[] a, final int key ) {
|
|
+ return binarySearch( a, 0, a.length, key );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final int[] a, int from, int to, final int key, final IntComparator c ) {
|
|
+ int midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ final int cmp = c.compare( midVal, key );
|
|
+ if ( cmp < 0 ) from = mid + 1;
|
|
+ else if (cmp > 0) to = mid - 1;
|
|
+ else return mid; // key found
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final int[] a, final int key, final IntComparator c ) {
|
|
+ return binarySearch( a, 0, a.length, key, c );
|
|
+ }
|
|
+ /** The size of a digit used during radix sort (must be a power of 2). */
|
|
+ private static final int DIGIT_BITS = 8;
|
|
+ /** The mask to extract a digit of {@link #DIGIT_BITS} bits. */
|
|
+ private static final int DIGIT_MASK = ( 1 << DIGIT_BITS ) - 1;
|
|
+ /** The number of digits per element. */
|
|
+ private static final int DIGITS_PER_ELEMENT = Integer.SIZE / DIGIT_BITS;
|
|
+ private static final int RADIXSORT_NO_REC = 1024;
|
|
+ private static final int PARALLEL_RADIXSORT_NO_FORK = 1024;
|
|
+ /** This method fixes negative numbers so that the combination exponent/significand is lexicographically sorted. */
|
|
+ /** Sorts the specified array using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation is significantly faster than quicksort
|
|
+ * already at small sizes (say, more than 10000 elements), but it can only
|
|
+ * sort in ascending order.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final int[] a ) {
|
|
+ radixSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of an array using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation is significantly faster than quicksort
|
|
+ * already at small sizes (say, more than 10000 elements), but it can only
|
|
+ * sort in ascending order.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final int[] a, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ quickSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = a[ i ];
|
|
+ c = ((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while ( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ c = ((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) quickSort( a, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ protected final static class Segment {
|
|
+ protected final int offset, length, level;
|
|
+ protected Segment( final int offset, final int length, final int level ) {
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ this.level = level;
|
|
+ }
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "Segment [offset=" + offset + ", length=" + length + ", level=" + level + "]";
|
|
+ }
|
|
+ }
|
|
+ protected final static Segment POISON_PILL = new Segment( -1, -1, -1 );
|
|
+ /** Sorts the specified range of an array using parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final int[] a, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ quickSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for(;;) {
|
|
+ if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = a[ i ];
|
|
+ c = ((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) {
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ c = ((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, i, i + count[ c ] );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts the specified array using parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final int[] a ) {
|
|
+ parallelRadixSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified array using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final int[] a, final boolean stable ) {
|
|
+ radixSortIndirect( perm, a, 0, perm.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified array using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
|
|
+ * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final int[] a, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, 0, perm, first, length );
|
|
+ for( int i = 0, p = first; i <= lastUsed; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, p, p + count[ i ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = p;
|
|
+ lengthStack[ stackPos ] = count[ i ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of an array using parallel indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void parallelRadixSortIndirect( final int perm[], final int[] a, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ radixSortIndirect( perm, a, from, to, stable );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for(;;) {
|
|
+ if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ ((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, first, perm, first, length );
|
|
+ for( int i = 0, p = first; i <= lastUsed; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, p, p + count[ i ], stable );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( p, count[ i ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = ((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, i, i + count[ c ], stable );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts the specified array using parallel indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void parallelRadixSortIndirect( final int perm[], final int[] a, final boolean stable ) {
|
|
+ parallelRadixSortIndirect( perm, a, 0, a.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using radix sort.
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final int[] a, final int[] b ) {
|
|
+ ensureSameLength( a, b );
|
|
+ radixSort( a, b, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final int[] a, final int[] b, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ selectionSort( a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = a[ i ];
|
|
+ int u = b[ i ];
|
|
+ c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ int z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ z = u;
|
|
+ u = b[ d ];
|
|
+ b[ d ] = z;
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ b[ i ] = u;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays using a parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final int[] a, final int[] b, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ quickSort( a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch." );
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ for ( int i = numberOfThreads; i-- != 0; )
|
|
+ executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for ( ;; ) {
|
|
+ if ( queueSize.get() == 0 ) for ( int i = numberOfThreads; i-- != 0; )
|
|
+ queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS;
|
|
+ // Count keys.
|
|
+ for ( int i = first + length; i-- != first; )
|
|
+ count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ for ( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = a[ i ];
|
|
+ int u = b[ i ];
|
|
+ c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while ( ( d = --pos[ c ] ) > i ) {
|
|
+ c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ final int z = t;
|
|
+ final int w = u;
|
|
+ t = a[ d ];
|
|
+ u = b[ d ];
|
|
+ a[ d ] = z;
|
|
+ b[ d ] = w;
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ b[ i ] = u;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for ( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch ( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts two arrays using a parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final int[] a, final int[] b ) {
|
|
+ ensureSameLength( a, b );
|
|
+ parallelRadixSort( a, b, 0, a.length );
|
|
+ }
|
|
+ private static void insertionSortIndirect( final int[] perm, final int[] a, final int[] b, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = perm[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ) || ( (a[ t ]) == (a[ u ]) ) && ( (b[ t ]) < (b[ u ]) ); u = perm[ --j - 1 ] ) {
|
|
+ perm[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ perm[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final int[] a, final int[] b, final boolean stable ) {
|
|
+ ensureSameLength( a, b );
|
|
+ radixSortIndirect( perm, a, b, 0, a.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
|
|
+ * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final int[] a, final int[] b, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ ((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, 0, perm, first, length );
|
|
+ for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, p, p + count[ i ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = p;
|
|
+ lengthStack[ stackPos ] = count[ i ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = ((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = ((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ private static void selectionSort( final int[][] a, final int from, final int to, final int level ) {
|
|
+ final int layers = a.length;
|
|
+ final int firstLayer = level / DIGITS_PER_ELEMENT;
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) {
|
|
+ for( int p = firstLayer; p < layers; p++ ) {
|
|
+ if ( a[ p ][ j ] < a[ p ][ m ] ) {
|
|
+ m = j;
|
|
+ break;
|
|
+ }
|
|
+ else if ( a[ p ][ j ] > a[ p ][ m ] ) break;
|
|
+ }
|
|
+ }
|
|
+ if ( m != i ) {
|
|
+ for( int p = layers; p-- != 0; ) {
|
|
+ final int u = a[ p ][ i ];
|
|
+ a[ p ][ i ] = a[ p ][ m ];
|
|
+ a[ p ][ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified array of arrays lexicographically using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
|
|
+ * in the same position will be considered a single key, and permuted
|
|
+ * accordingly.
|
|
+ *
|
|
+ * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
|
|
+ */
|
|
+ public static void radixSort( final int[][] a ) {
|
|
+ radixSort( a, 0, a[ 0 ].length );
|
|
+ }
|
|
+ /** Sorts the specified array of arrays lexicographically using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
|
|
+ * in the same position will be considered a single key, and permuted
|
|
+ * accordingly.
|
|
+ *
|
|
+ * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final int[][] a, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ selectionSort( a, from, to, 0 );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = a.length;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ for( int p = layers, l = a[ 0 ].length; p-- != 0; ) if ( a[ p ].length != l ) throw new IllegalArgumentException( "The array of index " + p + " has not the same length of the array of index 0." );
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] t = new int[ layers ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int[] k = a[ level / DIGITS_PER_ELEMENT ]; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ for( int p = layers; p-- != 0; ) t[ p ] = a[ p ][ i ];
|
|
+ c = ((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ c = ((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ for( int p = layers; p-- != 0; ) {
|
|
+ final int u = t[ p ];
|
|
+ t[ p ] = a[ p ][ d ];
|
|
+ a[ p ][ d ] = u;
|
|
+ }
|
|
+ }
|
|
+ for( int p = layers; p-- != 0; ) a[ p ][ i ] = t[ p ];
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, i, i + count[ c ], level + 1 );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param from the index of the first element (inclusive) to be shuffled.
|
|
+ * @param to the index of the last element (exclusive) to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static int[] shuffle( final int[] a, final int from, final int to, final Random random ) {
|
|
+ for( int i = to - from; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final int t = a[ from + i ];
|
|
+ a[ from + i ] = a[ from + p ];
|
|
+ a[ from + p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Shuffles the specified array using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static int[] shuffle( final int[] a, final Random random ) {
|
|
+ for( int i = a.length; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final int t = a[ i ];
|
|
+ a[ i ] = a[ p ];
|
|
+ a[ p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static int[] reverse( final int[] a ) {
|
|
+ final int length = a.length;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final int t = a[ length - i - 1 ];
|
|
+ a[ length - i - 1 ] = a[ i ];
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array fragment.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @param from the index of the first element (inclusive) to be reversed.
|
|
+ * @param to the index of the last element (exclusive) to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static int[] reverse( final int[] a, final int from, final int to ) {
|
|
+ final int length = to - from;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final int t = a[ from + length - i - 1 ];
|
|
+ a[ from + length - i - 1 ] = a[ from + i ];
|
|
+ a[ from + i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays. */
|
|
+ private static final class ArrayHashStrategy implements Hash.Strategy<int[]>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ public int hashCode( final int[] o ) {
|
|
+ return java.util.Arrays.hashCode( o );
|
|
+ }
|
|
+ public boolean equals( final int[] a, final int[] b ) {
|
|
+ return java.util.Arrays.equals( a, b );
|
|
+ }
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays.
|
|
+ *
|
|
+ * <P>This hash strategy may be used in custom hash collections whenever keys are
|
|
+ * arrays, and they must be considered equal by content. This strategy
|
|
+ * will handle <code>null</code> correctly, and it is serializable.
|
|
+ */
|
|
+ public final static Hash.Strategy<int[]> HASH_STRATEGY = new ArrayHashStrategy();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..04df663
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
|
|
@@ -0,0 +1,97 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface IntBidirectionalIterator extends IntIterator , ObjectBidirectionalIterator<Integer> {
|
|
+ /**
|
|
+ * Returns the previous element as a primitive type.
|
|
+ *
|
|
+ * @return the previous element in the iteration.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+ int previousInt();
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
|
|
new file mode 100644
|
|
index 0000000..56a2d21
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
|
|
@@ -0,0 +1,169 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface IntCollection extends Collection<Integer>, IntIterable {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ IntIterator iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntIterator intIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+ /**
|
|
+ * @see Collection#contains(Object)
|
|
+ */
|
|
+ boolean contains( int key );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray()
|
|
+ */
|
|
+ int[] toIntArray();
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ int[] toIntArray( int a[] );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ int[] toArray( int a[] );
|
|
+ /**
|
|
+ * @see Collection#add(Object)
|
|
+ */
|
|
+ boolean add( int key );
|
|
+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface
|
|
+ * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
|
|
+ * <code>remove()</code>.
|
|
+ *
|
|
+ * @see Collection#remove(Object)
|
|
+ */
|
|
+ boolean rem( int key );
|
|
+ /**
|
|
+ * @see Collection#addAll(Collection)
|
|
+ */
|
|
+ boolean addAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#containsAll(Collection)
|
|
+ */
|
|
+ boolean containsAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#removeAll(Collection)
|
|
+ */
|
|
+ boolean removeAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#retainAll(Collection)
|
|
+ */
|
|
+ boolean retainAll( IntCollection c );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
|
|
new file mode 100644
|
|
index 0000000..fbf2c95
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
|
|
@@ -0,0 +1,237 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntCollections {
|
|
+ private IntCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection extends AbstractIntCollection {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( int k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public int[] toIntArray( int[] a ) { return a; }
|
|
+ public int[] toIntArray() { return IntArrays.EMPTY_ARRAY; }
|
|
+ public boolean rem( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( IntCollection c ) { return c.isEmpty(); }
|
|
+
|
|
+ public IntBidirectionalIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection implements IntCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntCollection collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final IntCollection c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final IntCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final int o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public int[] toIntArray() { synchronized( sync ) { return collection.toIntArray(); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public int[] toIntArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
|
|
+ public int[] toArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
|
|
+ public boolean addAll( final IntCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final IntCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final IntCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final IntCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public boolean add( final Integer k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public IntIterator iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ public boolean add( final int k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final int k ) { synchronized( sync ) { return collection.rem( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection synchronize( final IntCollection c ) { return new SynchronizedCollection ( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection synchronize( final IntCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection implements IntCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntCollection collection;
|
|
+ protected UnmodifiableCollection( final IntCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final int o ) { return collection.contains( o ); }
|
|
+ public IntIterator iterator() { return IntIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ public int[] toIntArray() { return collection.toIntArray(); }
|
|
+ public int[] toIntArray( final int[] a ) { return collection.toIntArray( a ); }
|
|
+ public int[] toArray( final int[] a ) { return collection.toArray( a ); }
|
|
+ public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final IntCollection c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return collection.contains( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection unmodifiable( final IntCollection c ) { return new UnmodifiableCollection ( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection extends AbstractIntCollection implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntIterable iterable;
|
|
+ protected IterableCollection( final IntIterable iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final IntIterator iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public IntIterator iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static IntCollection asCollection( final IntIterable iterable ) {
|
|
+ if ( iterable instanceof IntCollection ) return (IntCollection )iterable;
|
|
+ return new IterableCollection ( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
|
|
new file mode 100644
|
|
index 0000000..cb84b48
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
|
|
@@ -0,0 +1,90 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Comparator;
|
|
+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
|
|
+ * and as primitive types.
|
|
+ *
|
|
+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
|
|
+ * can be used to implement this interface just by specifying the type-specific
|
|
+ * comparator.
|
|
+ *
|
|
+ * @see Comparator
|
|
+ */
|
|
+public interface IntComparator extends Comparator<Integer> {
|
|
+ /** Compares the given primitive types.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ * @return A positive integer, zero, or a negative integer if the first
|
|
+ * argument is greater than, equal to, or smaller than, respectively, the
|
|
+ * second one.
|
|
+ */
|
|
+ public int compare( int k1, int k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
|
|
new file mode 100644
|
|
index 0000000..04e7ce7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
|
|
@@ -0,0 +1,113 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with comparators.
|
|
+ */
|
|
+public class IntComparators {
|
|
+ private IntComparators() {}
|
|
+ /** A type-specific comparator mimicking the natural order. */
|
|
+ protected static class NaturalImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return ( Integer.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return NATURAL_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final IntComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
|
|
+ /** A type-specific comparator mimicking the opposite of the natural order. */
|
|
+ protected static class OppositeImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return - ( Integer.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return OPPOSITE_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final IntComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
|
|
+ protected static class OppositeComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final IntComparator comparator;
|
|
+ protected OppositeComparator( final IntComparator c ) {
|
|
+ comparator = c;
|
|
+ }
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return comparator.compare( b, a );
|
|
+ }
|
|
+ };
|
|
+ /** Returns a comparator representing the opposite order of the given comparator.
|
|
+ *
|
|
+ * @param c a comparator.
|
|
+ * @return a comparator representing the opposite order of <code>c</code>.
|
|
+ */
|
|
+ public static IntComparator oppositeComparator( final IntComparator c ) {
|
|
+ return new OppositeComparator ( c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
|
|
new file mode 100644
|
|
index 0000000..7b7753e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
|
|
@@ -0,0 +1,96 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+/** A type-specific {@link Hash} interface.
|
|
+ *
|
|
+ * @see Hash
|
|
+ */
|
|
+public interface IntHash {
|
|
+ /** A type-specific hash strategy.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Hash.Strategy
|
|
+ */
|
|
+ public interface Strategy {
|
|
+ /** Returns the hash code of the specified element with respect to this hash strategy.
|
|
+ *
|
|
+ * @param e an element.
|
|
+ * @return the hash code of the given element with respect to this hash strategy.
|
|
+ */
|
|
+ public int hashCode( int e );
|
|
+ /** Returns true if the given elements are equal with respect to this hash strategy.
|
|
+ *
|
|
+ * @param a an element.
|
|
+ * @param b another element.
|
|
+ * @return true if the two specified elements are equal with respect to this hash strategy.
|
|
+ */
|
|
+ public boolean equals( int a, int b );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..94da704
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
|
|
@@ -0,0 +1,227 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific heap-based indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use an additional <em>inversion array</em>, of the same length of the reference array,
|
|
+ * to keep track of the heap position containing a given element of the reference array. The priority queue is
|
|
+ * represented using a heap. The heap is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation does <em>not</em> allow one to enqueue several times the same index.
|
|
+ */
|
|
+public class IntHeapIndirectPriorityQueue extends IntHeapSemiIndirectPriorityQueue {
|
|
+ /** The inversion array. */
|
|
+ protected final int inv[];
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ super( refArray, capacity, c );
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ this.inv = new int[ refArray.length ];
|
|
+ Arrays.fill( inv, -1 );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ int i = size;
|
|
+ while( i-- != 0 ) {
|
|
+ if ( inv[ a[ i ] ] != -1 ) throw new IllegalArgumentException( "Index " + a[ i ] + " appears twice in the heap" );
|
|
+ inv[ a[ i ] ] = i;
|
|
+ }
|
|
+ IntIndirectHeaps.makeHeap( refArray, a, inv, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ public void enqueue( final int x ) {
|
|
+ if ( inv[ x ] >= 0 ) throw new IllegalArgumentException( "Index " + x + " belongs to the queue" );
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ inv[ heap[ size ] = x ] = size++;
|
|
+ IntIndirectHeaps.upHeap( refArray, heap, inv, size, size - 1, c );
|
|
+ }
|
|
+ public boolean contains( final int index ) {
|
|
+ return inv[ index ] >= 0;
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ if ( --size != 0 ) inv[ heap[ 0 ] = heap[ size ] ] = 0;
|
|
+ inv[ result ] = -1;
|
|
+ if ( size != 0 ) IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public void changed() {
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
|
|
+ }
|
|
+ public void changed( final int index ) {
|
|
+ final int pos = inv[ index ];
|
|
+ if ( pos < 0 ) throw new IllegalArgumentException( "Index " + index + " does not belong to the queue" );
|
|
+ final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, pos, c );
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
|
|
+ }
|
|
+ /** Rebuilds this heap in a bottom-up fashion.
|
|
+ */
|
|
+ public void allChanged() {
|
|
+ IntIndirectHeaps.makeHeap( refArray, heap, inv, size, c );
|
|
+ }
|
|
+ public boolean remove( final int index ) {
|
|
+ final int result = inv[ index ];
|
|
+ if ( result < 0 ) return false;
|
|
+ inv[ index ] = -1;
|
|
+ if ( result < --size ) {
|
|
+ inv[ heap[ result ] = heap[ size ] ] = result;
|
|
+ final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, result, c );
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ Arrays.fill( inv, -1 );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..b9f9796
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
|
|
@@ -0,0 +1,251 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific heap-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a heap. The heap is enlarged as needed, but
|
|
+ * it is never shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ */
|
|
+public class IntHeapPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The heap array. */
|
|
+
|
|
+ protected transient int[] heap = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public IntHeapPriorityQueue( int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( IntComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, int size, final IntComparator c ) {
|
|
+ this( c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ IntHeaps.makeHeap( a, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, final IntComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a type-specific collection using a given comparator.
|
|
+ *
|
|
+ * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final IntCollection collection, final IntComparator c ) {
|
|
+ this( collection.toIntArray(), c );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a type-specific collection using the natural order.
|
|
+ *
|
|
+ * <P>This constructor is
|
|
+ * more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final IntCollection collection ) {
|
|
+ this( collection, null );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a collection using a given comparator.
|
|
+ *
|
|
+ * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection, final IntComparator c ) {
|
|
+ this( collection.size(), c );
|
|
+ final Iterator<? extends Integer> iterator = collection.iterator();
|
|
+ final int size = collection.size();
|
|
+ for( int i = 0 ; i < size; i++ ) heap[ i ] = ((((Integer)(iterator.next())).intValue()));
|
|
+ }
|
|
+ /** Creates a queue using the elements in a collection using the natural order.
|
|
+ *
|
|
+ * <P>This constructor is
|
|
+ * more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection ) {
|
|
+ this( collection, null );
|
|
+ }
|
|
+ public void enqueue( int x ) {
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ heap[ size++ ] = x;
|
|
+ IntHeaps.upHeap( heap, size, size - 1, c );
|
|
+ }
|
|
+ public int dequeueInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ heap[ 0 ] = heap[ --size ];
|
|
+ if ( size != 0 ) IntHeaps.downHeap( heap, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return heap[ 0 ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ IntHeaps.downHeap( heap, size, 0, c );
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ /** Trims the underlying heap array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ heap = IntArrays.trim( heap, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( heap.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( heap[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ heap = new int[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) heap[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..f294993
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
|
|
@@ -0,0 +1,243 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
|
|
+/** A type-specific heap-based semi-indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use as reference list a <em>reference array</em>,
|
|
+ * which must be provided to each constructor. The priority queue is
|
|
+ * represented using a heap. The heap is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation allows one to enqueue several time the same index, but
|
|
+ * you must be careful when calling {@link #changed()}.
|
|
+ */
|
|
+public class IntHeapSemiIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
|
|
+ /** The reference array. */
|
|
+ protected final int refArray[];
|
|
+ /** The semi-indirect heap. */
|
|
+ protected int heap[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** Creates a new empty queue without elements with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.refArray = refArray;
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ IntSemiIndirectHeaps.makeHeap( refArray, a, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ /** Ensures that the given index is a valid reference.
|
|
+ *
|
|
+ * @param index an index in the reference array.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
|
|
+ */
|
|
+ protected void ensureElement( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
|
|
+ }
|
|
+ public void enqueue( int x ) {
|
|
+ ensureElement( x );
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ heap[ size++ ] = x;
|
|
+ IntSemiIndirectHeaps.upHeap( refArray, heap, size, size - 1, c );
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ heap[ 0 ] = heap[ --size ];
|
|
+ if ( size != 0 ) IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public int first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return heap[ 0 ];
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ *
|
|
+ * <P>The caller <strong>must</strong> guarantee that when this method is called the
|
|
+ * index of the first element appears just once in the queue. Failure to do so
|
|
+ * will bring the queue in an inconsistent state, and will cause
|
|
+ * unpredictable behaviour.
|
|
+ */
|
|
+ public void changed() {
|
|
+ IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
|
|
+ }
|
|
+ /** Rebuilds this heap in a bottom-up fashion.
|
|
+ */
|
|
+ public void allChanged() {
|
|
+ IntSemiIndirectHeaps.makeHeap( refArray, heap, size, c );
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() { size = 0; }
|
|
+ /** Trims the backing array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ heap = IntArrays.trim( heap, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ public int front( final int[] a ) {
|
|
+ return c == null ? IntSemiIndirectHeaps.front( refArray, heap, size, a ) : IntSemiIndirectHeaps.front( refArray, heap, size, a, c );
|
|
+ }
|
|
+ public String toString() {
|
|
+ StringBuffer s = new StringBuffer();
|
|
+ s.append( "[" );
|
|
+ for ( int i = 0; i < size; i++ ) {
|
|
+ if ( i != 0 ) s.append( ", " );
|
|
+ s.append( refArray[ heap [ i ] ] );
|
|
+ }
|
|
+ s.append( "]" );
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
|
|
new file mode 100644
|
|
index 0000000..ab987b7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
|
|
@@ -0,0 +1,155 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with heaps.
|
|
+ *
|
|
+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
|
|
+ * are used in the implementation of heap-based queues, but they may be also used
|
|
+ * directly.
|
|
+ *
|
|
+ */
|
|
+public class IntHeaps {
|
|
+ private IntHeaps() {}
|
|
+ /** Moves the given element down into the heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
|
|
+ if ( ( (e) <= (t) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( e, t ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (t) <= (e) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( t, e ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Makes an array into a heap.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] heap, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( heap, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
|
|
new file mode 100644
|
|
index 0000000..53f3e35
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
|
|
@@ -0,0 +1,191 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Arrays;
|
|
+/** A class providing static methods and objects that do useful things with indirect heaps.
|
|
+ *
|
|
+ * <P>An indirect heap is an extension of a semi-indirect heap using also an
|
|
+ * <em>inversion array</em> of the same length as the reference array,
|
|
+ * satisfying the relation <code>heap[inv[i]]==i</code> when
|
|
+ * <code>inv[i]>=0</code>, and <code>inv[heap[i]]==i</code> for all elements in the heap.
|
|
+ */
|
|
+public class IntIndirectHeaps {
|
|
+ private IntIndirectHeaps() {}
|
|
+ /** Moves the given element down into the indirect heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the indirect heap (starting at 0).
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
|
|
+ if ( ( (E) <= (refArray[ t ]) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ inv[ e ] = i;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the indirect heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * Note that in principle after this call the heap property may be violated.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the indirect heap (starting at 0).
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (refArray[ t ]) <= (E) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( refArray[ t ], E ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ inv[ e ] = i;
|
|
+ return i;
|
|
+ }
|
|
+ /** Creates an indirect heap in the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param heap the array where the heap is to be created.
|
|
+ * @param inv the inversion array.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final int[] inv, final IntComparator c ) {
|
|
+ IntArrays.ensureOffsetLength( refArray, offset, length );
|
|
+ if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
|
|
+ if ( inv.length < refArray.length ) throw new IllegalArgumentException( "The inversion array length (" + heap.length + ") is smaller than the length of the reference array (" + refArray.length + ")" );
|
|
+ Arrays.fill( inv, 0, refArray.length, -1 );
|
|
+ int i = length;
|
|
+ while( i-- != 0 ) inv[ heap[ i ] = offset + i ] = i;
|
|
+ i = length >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, inv, length, i, c );
|
|
+ }
|
|
+ /** Creates an indirect heap from a given index array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, inv, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..a950eff
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
|
|
@@ -0,0 +1,85 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.IndirectPriorityQueue;
|
|
+/** A type-specific {@link IndirectPriorityQueue}.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface IntIndirectPriorityQueue extends IndirectPriorityQueue<Integer> {
|
|
+ /** Returns the comparator associated with this queue.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link IndirectPriorityQueue}.
|
|
+ *
|
|
+ * @return the comparator associated with this queue.
|
|
+ * @see IndirectPriorityQueue#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
|
|
new file mode 100644
|
|
index 0000000..a0c323f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
|
|
@@ -0,0 +1,88 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “colon” <code>for</code> statements with primitive-type
|
|
+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
|
|
+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
|
|
+ *
|
|
+ * @see Iterable
|
|
+ */
|
|
+public interface IntIterable extends Iterable<Integer> {
|
|
+ /** Returns a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * @return a type-specific iterator.
|
|
+ */
|
|
+ IntIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
|
|
new file mode 100644
|
|
index 0000000..c6e9fc9
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
|
|
@@ -0,0 +1,96 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface IntIterator extends Iterator<Integer> {
|
|
+ /**
|
|
+ * Returns the next element as a primitive type.
|
|
+ *
|
|
+ * @return the next element in the iteration.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int nextInt();
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
|
|
new file mode 100644
|
|
index 0000000..324c12c
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
|
|
@@ -0,0 +1,637 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class IntIterators {
|
|
+ private IntIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator extends AbstractIntListIterator implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public int nextInt() { throw new NoSuchElementException(); }
|
|
+ public int previousInt() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator extends AbstractIntListIterator {
|
|
+ private final int element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static IntListIterator singleton( final int element ) {
|
|
+ return new SingletonIterator ( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator extends AbstractIntListIterator {
|
|
+ private final int[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final int[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static IntListIterator wrap( final int[] array, final int offset, final int length ) {
|
|
+ IntArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator ( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static IntListIterator wrap( final int[] array ) {
|
|
+ return new ArrayIterator ( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final int array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextInt();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final int array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+
|
|
+ public static int[] unwrap( final IntIterator i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int array[] = new int[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = IntArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.nextInt();
|
|
+ }
|
|
+ return IntArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static int[] unwrap( final IntIterator i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final IntCollection c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.nextInt() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static long unwrap( final IntIterator i, final IntCollection c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.nextInt() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final IntIterator i, final IntCollection s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.nextInt() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final IntIterator i, final IntCollection s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static IntList pour( final IntIterator i, int max ) {
|
|
+ final IntArrayList l = new IntArrayList ();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static IntList pour( final IntIterator i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper extends AbstractIntIterator {
|
|
+ final Iterator<Integer> i;
|
|
+ public IteratorWrapper( final Iterator<Integer> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public int nextInt() { return ((i.next()).intValue()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static IntIterator asIntIterator( final Iterator i ) {
|
|
+ if ( i instanceof IntIterator ) return (IntIterator )i;
|
|
+ return new IteratorWrapper ( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper extends AbstractIntListIterator {
|
|
+ final ListIterator<Integer> i;
|
|
+ public ListIteratorWrapper( final ListIterator<Integer> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( int k ) { i.set( (Integer.valueOf(k)) ); }
|
|
+ public void add( int k ) { i.add( (Integer.valueOf(k)) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public int nextInt() { return ((i.next()).intValue()); }
|
|
+ public int previousInt() { return ((i.previous()).intValue()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static IntListIterator asIntIterator( final ListIterator i ) {
|
|
+ if ( i instanceof IntListIterator ) return (IntListIterator )i;
|
|
+ return new ListIteratorWrapper ( i );
|
|
+ }
|
|
+ private static class IntervalIterator extends AbstractIntListIterator {
|
|
+ private final int from, to;
|
|
+ int curr;
|
|
+ public IntervalIterator( final int from, final int to ) {
|
|
+ this.from = this.curr = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < to; }
|
|
+ public boolean hasPrevious() { return curr > from; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return curr++;
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return --curr;
|
|
+ }
|
|
+ public int nextIndex() { return curr - from; }
|
|
+ public int previousIndex() { return curr - from - 1; }
|
|
+ public int skip( int n ) {
|
|
+ if ( curr + n <= to ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = to - curr;
|
|
+ curr = to;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( curr - n >= from ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr - from ;
|
|
+ curr = from;
|
|
+ return n;
|
|
+ }
|
|
+ }
|
|
+ /** Creates a type-specific list iterator over an interval.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return the
|
|
+ * elements <code>from</code>, <code>from+1</code>,…, <code>to-1</code>.
|
|
+ *
|
|
+ * @param from the starting element (inclusive).
|
|
+ * @param to the ending element (exclusive).
|
|
+ * @return a type-specific list iterator enumerating the elements from <code>from</code> to <code>to</code>.
|
|
+ */
|
|
+ public static IntListIterator fromTo( final int from, final int to ) {
|
|
+ return new IntervalIterator( from, to );
|
|
+ }
|
|
+ private static class IteratorConcatenator extends AbstractIntIterator {
|
|
+ final IntIterator a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final IntIterator a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ int next = a[ lastOffset = offset ].nextInt();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static IntIterator concat( final IntIterator a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static IntIterator concat( final IntIterator a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator ( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator extends AbstractIntIterator {
|
|
+ final protected IntIterator i;
|
|
+ public UnmodifiableIterator( final IntIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static IntIterator unmodifiable( final IntIterator i ) { return new UnmodifiableIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator extends AbstractIntBidirectionalIterator {
|
|
+ final protected IntBidirectionalIterator i;
|
|
+ public UnmodifiableBidirectionalIterator( final IntBidirectionalIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ public int previousInt() { return i.previousInt(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static IntBidirectionalIterator unmodifiable( final IntBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator extends AbstractIntListIterator {
|
|
+ final protected IntListIterator i;
|
|
+ public UnmodifiableListIterator( final IntListIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ public int previousInt() { return i.previousInt(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static IntListIterator unmodifiable( final IntListIterator i ) { return new UnmodifiableListIterator ( i ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
|
|
new file mode 100644
|
|
index 0000000..ac197b8
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
|
|
@@ -0,0 +1,1071 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific linked hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
|
|
+ * have been added to the set (addition of elements already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted set, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first element
|
|
+ * in iteration order with {@code first()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
|
|
+ * contract because all subset methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by this class are type-specific {@linkplain
|
|
+ * java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is in the set</em> (if the provided element
|
|
+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
|
|
+ * If, however, the provided element is not the first or last element in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class IntLinkedOpenCustomHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The hash strategy of this custom set. */
|
|
+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntCollection c, final float f, it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntCollection c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntIterator i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f, strategy );
|
|
+ while( i.hasNext() ) add( i.nextInt() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntIterator i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( IntIterators.asIntIterator( i ), f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( IntIterators.asIntIterator( i ), strategy );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( length < 0 ? 0 : length, f, strategy );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, 0, a.length, f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash set.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ key[ n ] = k;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /** Removes the first key in iteration order.
|
|
+ * @return the first key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeFirstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ /** Removes the the last key in iteration order.
|
|
+ * @return the last key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeLastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToFirst( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ // There's always an unused entry. TODO
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToLast( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToLast( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET(link[ d ], -1, -1)
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first element of this set in iteration order.
|
|
+ *
|
|
+ * @return the first element in iteration order.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last element of this set in iteration order.
|
|
+ *
|
|
+ * @return the last element in iteration order.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ /** A list iterator over a linked set.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time.
|
|
+ */
|
|
+ private class SetIterator extends AbstractIntListIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
|
|
+ int index = -1;
|
|
+ SetIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ SetIterator( int from ) {
|
|
+ if ( ( strategy.equals( (from), (0) ) ) ) {
|
|
+ if ( IntLinkedOpenCustomHashSet.this.containsNull ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ if ( ( strategy.equals( (key[ last ]), (from) ) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ final int key[] = IntLinkedOpenCustomHashSet.this.key;
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (key[ pos ]), (from) ) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ IntLinkedOpenCustomHashSet.this.containsNull = false;
|
|
+ IntLinkedOpenCustomHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = IntLinkedOpenCustomHashSet.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
|
|
+ * Please see the class documentation for implementation details.
|
|
+ *
|
|
+ * @param from an element to start from.
|
|
+ * @return a type-specific list iterator starting at the given element.
|
|
+ * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
|
|
+ */
|
|
+ public IntListIterator iterator( int from ) {
|
|
+ return new SetIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( strategy.equals( (key[ i ]), (0) ) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenCustomHashSet clone() {
|
|
+ IntLinkedOpenCustomHashSet c;
|
|
+ try {
|
|
+ c = (IntLinkedOpenCustomHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.link = link.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += ( strategy.hashCode(key[ i ]) );
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final IntIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
|
|
new file mode 100644
|
|
index 0000000..8d7e9ad
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
|
|
@@ -0,0 +1,1044 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific linked hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
|
|
+ * have been added to the set (addition of elements already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted set, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first element
|
|
+ * in iteration order with {@code first()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
|
|
+ * contract because all subset methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by this class are type-specific {@linkplain
|
|
+ * java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is in the set</em> (if the provided element
|
|
+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
|
|
+ * If, however, the provided element is not the first or last element in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class IntLinkedOpenHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenHashSet( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntCollection c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntCollection c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntIterator i, final float f ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f );
|
|
+ while( i.hasNext() ) add( i.nextInt() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntIterator i ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Iterator<?> i, final float f ) {
|
|
+ this( IntIterators.asIntIterator( i ), f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Iterator<?> i ) {
|
|
+ this( IntIterators.asIntIterator( i ) );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length, final float f ) {
|
|
+ this( length < 0 ? 0 : length, f );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final float f ) {
|
|
+ this( a, 0, a.length, f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNull;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /** Removes the first key in iteration order.
|
|
+ * @return the first key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeFirstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ /** Removes the the last key in iteration order.
|
|
+ * @return the last key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeLastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToFirst( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ // There's always an unused entry. TODO
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (k) == (key[ pos ]) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToLast( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToLast( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (k) == (key[ pos ]) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET(link[ d ], -1, -1)
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first element of this set in iteration order.
|
|
+ *
|
|
+ * @return the first element in iteration order.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last element of this set in iteration order.
|
|
+ *
|
|
+ * @return the last element in iteration order.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ /** A list iterator over a linked set.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time.
|
|
+ */
|
|
+ private class SetIterator extends AbstractIntListIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
|
|
+ int index = -1;
|
|
+ SetIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ SetIterator( int from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( IntLinkedOpenHashSet.this.containsNull ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ final int key[] = IntLinkedOpenHashSet.this.key;
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ IntLinkedOpenHashSet.this.containsNull = false;
|
|
+ IntLinkedOpenHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = IntLinkedOpenHashSet.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
|
|
+ * Please see the class documentation for implementation details.
|
|
+ *
|
|
+ * @param from an element to start from.
|
|
+ * @return a type-specific list iterator starting at the given element.
|
|
+ * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
|
|
+ */
|
|
+ public IntListIterator iterator( int from ) {
|
|
+ return new SetIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenHashSet clone() {
|
|
+ IntLinkedOpenHashSet c;
|
|
+ try {
|
|
+ c = (IntLinkedOpenHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += (key[ i ]);
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final IntIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
|
|
new file mode 100644
|
|
index 0000000..b8aeebd
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
|
|
@@ -0,0 +1,210 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface IntList extends List<Integer>, Comparable<List<? extends Integer>>, IntCollection {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ IntListIterator iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntListIterator intListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntListIterator intListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ IntListIterator listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ IntListIterator listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntList intSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ IntList subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, int a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, int a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, int a[], int offset, int length );
|
|
+ /**
|
|
+ * @see List#add(Object)
|
|
+ */
|
|
+ boolean add( int key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ void add( int index, int key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, IntCollection c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, IntList c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( IntList c );
|
|
+ /**
|
|
+ * @see List#get(int)
|
|
+ */
|
|
+ int getInt( int index );
|
|
+ /**
|
|
+ * @see List#indexOf(Object)
|
|
+ */
|
|
+ int indexOf( int k );
|
|
+ /**
|
|
+ * @see List#lastIndexOf(Object)
|
|
+ */
|
|
+ int lastIndexOf( int k );
|
|
+ /**
|
|
+ * @see List#remove(int)
|
|
+ */
|
|
+ int removeInt( int index );
|
|
+ /**
|
|
+ * @see List#set(int,Object)
|
|
+ */
|
|
+ int set( int index, int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
|
|
new file mode 100644
|
|
index 0000000..758146f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
|
|
@@ -0,0 +1,85 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface IntListIterator extends ListIterator<Integer>, IntBidirectionalIterator {
|
|
+ void set( int k );
|
|
+ void add( int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
|
|
new file mode 100644
|
|
index 0000000..ea909a8
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
|
|
@@ -0,0 +1,334 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+import java.util.Collection;
|
|
+import java.util.Random;
|
|
+/** A class providing static methods and objects that do useful things with type-specific lists.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntLists {
|
|
+ private IntLists() {}
|
|
+ /** Shuffles the specified list using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param l the list to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>l</code>.
|
|
+ */
|
|
+ public static IntList shuffle( final IntList l, final Random random ) {
|
|
+ for( int i = l.size(); i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final int t = l.getInt( i );
|
|
+ l.set( i, l.getInt( p ) );
|
|
+ l.set( p, t );
|
|
+ }
|
|
+ return l;
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class EmptyList extends IntCollections.EmptyCollection implements IntList , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyList() {}
|
|
+ public void add( final int index, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int removeInt( int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int set( final int index, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( int k ) { return -1; }
|
|
+ public int lastIndexOf( int k ) { return -1; }
|
|
+ public boolean addAll( Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer get( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( IntList c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, IntList c ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer set( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public int getInt( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public Integer remove( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( Object k ) { return -1; }
|
|
+ public int lastIndexOf( Object k ) { return -1; }
|
|
+ //SUPPRESS_WARNINGS_KEY_UNCHECKED
|
|
+ //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+
|
|
+ public IntIterator intIterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator listIterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator listIterator( int i ) { if ( i == 0 ) return IntIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( int i ) { return listIterator( i ); }
|
|
+ public IntList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( int from, int to ) { return subList( from, to ); }
|
|
+ public void getElements( int from, int[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
|
|
+ public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( int s ) { throw new UnsupportedOperationException(); }
|
|
+ public int compareTo( final List<? extends Integer> o ) {
|
|
+ if ( o == this ) return 0;
|
|
+ return ((List<?>)o).isEmpty() ? 0 : -1;
|
|
+ }
|
|
+ private Object readResolve() { return EMPTY_LIST; }
|
|
+ public Object clone() { return EMPTY_LIST; }
|
|
+ public int hashCode() { return 1; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
|
|
+ public String toString() { return "[]"; }
|
|
+ }
|
|
+ /** An empty list (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptyList EMPTY_LIST = new EmptyList();
|
|
+ /** An immutable class representing a type-specific singleton list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class Singleton extends AbstractIntList implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private final int element;
|
|
+ private Singleton( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public int getInt( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
|
|
+ public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final int k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final Collection <? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public int[] toIntArray() {
|
|
+ int a[] = new int[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public IntListIterator listIterator() { return IntIterators.singleton( element ); }
|
|
+ public IntListIterator iterator() { return listIterator(); }
|
|
+ public IntListIterator listIterator( int i ) {
|
|
+ if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
|
|
+ IntListIterator l = listIterator();
|
|
+ if ( i == 1 ) l.next();
|
|
+ return l;
|
|
+ }
|
|
+
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( from != 0 || to != 1 ) return EMPTY_LIST;
|
|
+ return this;
|
|
+ }
|
|
+ public int size() { return 1; }
|
|
+ public void size( final int size ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return this; }
|
|
+ public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntList singleton( final int element ) { return new Singleton ( element ); }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntList singleton( final Object element ) { return new Singleton ( ((((Integer)(element)).intValue())) ); }
|
|
+ /** A synchronized wrapper class for lists. */
|
|
+ public static class SynchronizedList extends IntCollections.SynchronizedCollection implements IntList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected SynchronizedList( final IntList l, final Object sync ) {
|
|
+ super( l, sync );
|
|
+ this.list = l;
|
|
+ }
|
|
+ protected SynchronizedList( final IntList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public int getInt( final int i ) { synchronized( sync ) { return list.getInt( i ); } }
|
|
+ public int set( final int i, final int k ) { synchronized( sync ) { return list.set( i, k ); } }
|
|
+ public void add( final int i, final int k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public int removeInt( final int i ) { synchronized( sync ) { return list.removeInt( i ); } }
|
|
+ public int indexOf( final int k ) { synchronized( sync ) { return list.indexOf( k ); } }
|
|
+ public int lastIndexOf( final int k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public void getElements( final int from, final int a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
|
|
+ public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
|
|
+ public void addElements( int index, final int a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
|
|
+ public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
|
|
+ public IntListIterator iterator() { return list.listIterator(); }
|
|
+ public IntListIterator listIterator() { return list.listIterator(); }
|
|
+ public IntListIterator listIterator( final int i ) { return list.listIterator( i ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
|
|
+ public IntList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ public int compareTo( final List<? extends Integer> o ) { synchronized( sync ) { return list.compareTo( o ); } }
|
|
+ public boolean addAll( final int index, final IntCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public boolean addAll( final int index, IntList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
|
|
+ public boolean addAll( IntList l ) { synchronized( sync ) { return list.addAll( l ); } }
|
|
+ public Integer get( final int i ) { synchronized( sync ) { return list.get( i ); } }
|
|
+ public void add( final int i, Integer k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public Integer set( final int index, Integer k ) { synchronized( sync ) { return list.set( index, k ); } }
|
|
+ public Integer remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
|
|
+ public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
|
|
+ public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static IntList synchronize( final IntList l ) { return new SynchronizedList ( l ); }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @param sync an object that will be used to synchronize the access to the list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static IntList synchronize( final IntList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
|
|
+ /** An unmodifiable wrapper class for lists. */
|
|
+ public static class UnmodifiableList extends IntCollections.UnmodifiableCollection implements IntList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected UnmodifiableList( final IntList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public int getInt( final int i ) { return list.getInt( i ); }
|
|
+ public int set( final int i, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int i, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final int k ) { return list.indexOf( k ); }
|
|
+ public int lastIndexOf( final int k ) { return list.lastIndexOf( k ); }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void getElements( final int from, final int a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
|
|
+ public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( final int size ) { list.size( size ); }
|
|
+ public IntListIterator iterator() { return listIterator(); }
|
|
+ public IntListIterator listIterator() { return IntIterators.unmodifiable( list.listIterator() ); }
|
|
+ public IntListIterator listIterator( final int i ) { return IntIterators.unmodifiable( list.listIterator( i ) ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
|
|
+ public IntList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ public int compareTo( final List<? extends Integer> o ) { return list.compareTo( o ); }
|
|
+ public boolean addAll( final int index, final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntList l ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int index, final IntList l ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer get( final int i ) { return list.get( i ); }
|
|
+ public void add( final int i, Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer set( final int index, Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer remove( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final Object o ) { return list.indexOf( o ); }
|
|
+ public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in an unmodifiable list.
|
|
+ * @return an unmodifiable view of the specified list.
|
|
+ * @see java.util.Collections#unmodifiableList(List)
|
|
+ */
|
|
+ public static IntList unmodifiable( final IntList l ) { return new UnmodifiableList ( l ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..7517420
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
|
|
@@ -0,0 +1,108 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface IntPriorityQueue extends PriorityQueue<Integer> {
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue.
|
|
+ */
|
|
+ void enqueue( int x );
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int dequeueInt();
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int firstInt();
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int lastInt();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
|
|
+ *
|
|
+ * @see PriorityQueue#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000..4d54aa0
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
|
|
@@ -0,0 +1,116 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with type-specific priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+public class IntPriorityQueues {
|
|
+ private IntPriorityQueues() {}
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+ public static class SynchronizedPriorityQueue implements IntPriorityQueue {
|
|
+ final protected IntPriorityQueue q;
|
|
+ final protected Object sync;
|
|
+ protected SynchronizedPriorityQueue( final IntPriorityQueue q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedPriorityQueue( final IntPriorityQueue q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public int dequeueInt() { synchronized( sync ) { return q.dequeueInt(); } }
|
|
+ public int firstInt() { synchronized( sync ) { return q.firstInt(); } }
|
|
+ public int lastInt() { synchronized( sync ) { return q.lastInt(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public IntComparator comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public void enqueue( Integer x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public Integer dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public Integer first() { synchronized( sync ) { return q.first(); } }
|
|
+ public Integer last() { synchronized( sync ) { return q.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static IntPriorityQueue synchronize( final IntPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static IntPriorityQueue synchronize( final IntPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
|
|
new file mode 100644
|
|
index 0000000..9e517f5
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
|
|
@@ -0,0 +1,268 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+/** A class providing static methods and objects that do useful things with semi-indirect heaps.
|
|
+ *
|
|
+ * <P>A semi-indirect heap is based on a <em>reference array</em>. Elements of
|
|
+ * a semi-indirect heap are integers that index the reference array (note that
|
|
+ * in an <em>indirect</em> heap you can also map elements of the reference
|
|
+ * array to heap positions).
|
|
+ */
|
|
+public class IntSemiIndirectHeaps {
|
|
+ private IntSemiIndirectHeaps() {}
|
|
+ /** Moves the given element down into the semi-indirect heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the semi-indirect heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
|
|
+ if ( ( (E) <= (refArray[ t ]) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the semi-indirect heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the semi-indirect heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (refArray[ t ]) <= (E) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( refArray[ t ], E ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Creates a semi-indirect heap in the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param heap the array where the heap is to be created.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final IntComparator c ) {
|
|
+ IntArrays.ensureOffsetLength( refArray, offset, length );
|
|
+ if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
|
|
+ int i = length;
|
|
+ while( i-- != 0 ) heap[ i ] = offset + i;
|
|
+ i = length >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, length, i, c );
|
|
+ }
|
|
+ /** Creates a semi-indirect heap, allocating its heap array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the heap array.
|
|
+ */
|
|
+ public static int[] makeHeap( final int[] refArray, final int offset, final int length, final IntComparator c ) {
|
|
+ final int[] heap = length <= 0 ? IntArrays.EMPTY_ARRAY : new int[ length ];
|
|
+ makeHeap( refArray, offset, length, heap, c );
|
|
+ return heap;
|
|
+ }
|
|
+ /** Creates a semi-indirect heap from a given index array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int[] heap, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, size, i, c );
|
|
+ }
|
|
+ /** Retrieves the front of a heap in a given array.
|
|
+ *
|
|
+ * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the first index.
|
|
+ *
|
|
+ * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
|
|
+ * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that
|
|
+ * terminates when all visited nodes are larger than the element associated
|
|
+ * to the top index, which implies that no elements of the front can be found later.
|
|
+ * In most cases this trick yields a significant improvement.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+
|
|
+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a ) {
|
|
+ final int top = refArray[ heap[ 0 ] ];
|
|
+ int j = 0, // The current position in a
|
|
+ l = 0, // The first position to visit in the next level (inclusive)
|
|
+ r = 1, // The last position to visit in the next level (exclusive)
|
|
+ f = 0; // The first position (in the heap array) of the next level
|
|
+ for( int i = 0; i < r; i++ ) {
|
|
+ if ( i == f ) { // New level
|
|
+ if ( l >= r ) break; // If we are crossing the two bounds, we're over
|
|
+ f = (f << 1) + 1; // Update the first position of the next level...
|
|
+ i = l; // ...and jump directly to position l
|
|
+ l = -1; // Invalidate l
|
|
+ }
|
|
+ if ( ( (top) == (refArray[ heap[ i ] ]) ) ) {
|
|
+ a[ j++ ] = heap[ i ];
|
|
+ if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
|
|
+ r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
|
|
+ }
|
|
+ }
|
|
+ return j;
|
|
+ }
|
|
+ /** Retrieves the front of a heap in a given array using a given comparator.
|
|
+ *
|
|
+ * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the first index.
|
|
+ *
|
|
+ * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
|
|
+ * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that
|
|
+ * terminates when all visited nodes are larger than the element associated
|
|
+ * to the top index, which implies that no elements of the front can be found later.
|
|
+ * In most cases this trick yields a significant improvement.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
|
|
+ * @param c a type-specific comparator.
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a, final IntComparator c ) {
|
|
+ final int top = refArray[ heap[ 0 ] ];
|
|
+ int j = 0, // The current position in a
|
|
+ l = 0, // The first position to visit in the next level (inclusive)
|
|
+ r = 1, // The last position to visit in the next level (exclusive)
|
|
+ f = 0; // The first position (in the heap array) of the next level
|
|
+ for( int i = 0; i < r; i++ ) {
|
|
+ if ( i == f ) { // New level
|
|
+ if ( l >= r ) break; // If we are crossing the two bounds, we're over
|
|
+ f = (f << 1) + 1; // Update the first position of the next level...
|
|
+ i = l; // ...and jump directly to position l
|
|
+ l = -1; // Invalidate l
|
|
+ }
|
|
+ if ( c.compare( top, refArray[ heap[ i ] ] ) == 0 ) {
|
|
+ a[ j++ ] = heap[ i ];
|
|
+ if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
|
|
+ r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
|
|
+ }
|
|
+ }
|
|
+ return j;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
|
|
new file mode 100644
|
|
index 0000000..9d8a21f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
|
|
@@ -0,0 +1,97 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface IntSet extends IntCollection , Set<Integer> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ IntIterator iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
|
|
new file mode 100644
|
|
index 0000000..69c8c44
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
|
|
@@ -0,0 +1,186 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntSets {
|
|
+ private IntSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet extends IntCollections.EmptyCollection implements IntSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton extends AbstractIntSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final int element;
|
|
+ protected Singleton( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final int k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public int[] toIntArray() {
|
|
+ int a[] = new int[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public IntListIterator iterator() { return IntIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSet singleton( final int element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSet singleton( final Integer element ) {
|
|
+ return new Singleton ( ((element).intValue()) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet extends IntCollections.SynchronizedCollection implements IntSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final IntSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final IntSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final int k ) { synchronized( sync ) { return collection.remove( (Integer.valueOf(k)) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static IntSet synchronize( final IntSet s ) { return new SynchronizedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static IntSet synchronize( final IntSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet extends IntCollections.UnmodifiableCollection implements IntSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final IntSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static IntSet unmodifiable( final IntSet s ) { return new UnmodifiableSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..ba95523
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
|
|
@@ -0,0 +1,179 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface IntSortedSet extends IntSet , SortedSet<Integer> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ IntBidirectionalIterator iterator( int fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntBidirectionalIterator intIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ IntBidirectionalIterator iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ IntSortedSet subSet( Integer fromElement, Integer toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ IntSortedSet headSet( Integer toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ IntSortedSet tailSet( Integer fromElement );
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
|
|
+ *
|
|
+ * @see SortedSet#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+ /**
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ IntSortedSet subSet( int fromElement, int toElement) ;
|
|
+ /**
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ IntSortedSet headSet( int toElement );
|
|
+ /**
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ IntSortedSet tailSet( int fromElement );
|
|
+ /**
|
|
+ * @see SortedSet#first()
|
|
+ */
|
|
+ int firstInt();
|
|
+ /**
|
|
+ * @see SortedSet#last()
|
|
+ */
|
|
+ int lastInt();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
|
|
new file mode 100644
|
|
index 0000000..56623dc
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
|
|
@@ -0,0 +1,280 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntSortedSets {
|
|
+ private IntSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet extends IntSets.EmptySet implements IntSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return iterator(); }
|
|
+
|
|
+ public IntBidirectionalIterator iterator( int from ) { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntSortedSet subSet( int from, int to ) { return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet headSet( int from ) { return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet tailSet( int to ) { return EMPTY_SET; }
|
|
+ public int firstInt() { throw new NoSuchElementException(); }
|
|
+ public int lastInt() { throw new NoSuchElementException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ public IntSortedSet subSet( Integer from, Integer to ) { return EMPTY_SET; }
|
|
+ public IntSortedSet headSet( Integer from ) { return EMPTY_SET; }
|
|
+ public IntSortedSet tailSet( Integer to ) { return EMPTY_SET; }
|
|
+ public Integer first() { throw new NoSuchElementException(); }
|
|
+ public Integer last() { throw new NoSuchElementException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton extends IntSets.Singleton implements IntSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final IntComparator comparator;
|
|
+ private Singleton( final int element, final IntComparator comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final int element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final int k1, final int k2 ) {
|
|
+ return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public IntBidirectionalIterator iterator( int from ) {
|
|
+ IntBidirectionalIterator i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public IntComparator comparator() { return comparator; }
|
|
+
|
|
+ public IntSortedSet subSet( final int from, final int to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet headSet( final int to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet tailSet( final int from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public int firstInt() { return element; }
|
|
+ public int lastInt() { return element; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() { return (Integer.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() { return (Integer.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return subSet( ((from).intValue()), ((to).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet headSet( final Integer to ) { return headSet( ((to).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet tailSet( final Integer from ) { return tailSet( ((from).intValue()) ); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final int element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final int element, final IntComparator comparator ) {
|
|
+ return new Singleton ( element, comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final Object element ) {
|
|
+ return new Singleton( ((((Integer)(element)).intValue())) );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final Object element, final IntComparator comparator ) {
|
|
+ return new Singleton( ((((Integer)(element)).intValue())), comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet extends IntSets.SynchronizedSet implements IntSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntSortedSet sortedSet;
|
|
+ protected SynchronizedSortedSet( final IntSortedSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final IntSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public IntComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
|
|
+ public IntSortedSet headSet( final int to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
|
|
+ public IntSortedSet tailSet( final int from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
|
|
+ public IntBidirectionalIterator iterator() { return sortedSet.iterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return sortedSet.iterator(); }
|
|
+ public int firstInt() { synchronized( sync ) { return sortedSet.firstInt(); } }
|
|
+ public int lastInt() { synchronized( sync ) { return sortedSet.lastInt(); } }
|
|
+ public Integer first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public Integer last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
|
|
+ public IntSortedSet headSet( final Integer to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
|
|
+ public IntSortedSet tailSet( final Integer from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet synchronize( final IntSortedSet s ) { return new SynchronizedSortedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet synchronize( final IntSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet extends IntSets.UnmodifiableSet implements IntSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntSortedSet sortedSet;
|
|
+ protected UnmodifiableSortedSet( final IntSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public IntComparator comparator() { return sortedSet.comparator(); }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
|
|
+ public IntSortedSet headSet( final int to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
|
|
+ public IntSortedSet tailSet( final int from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
|
|
+ public IntBidirectionalIterator iterator() { return IntIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return IntIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return iterator(); }
|
|
+ public int firstInt() { return sortedSet.firstInt(); }
|
|
+ public int lastInt() { return sortedSet.lastInt(); }
|
|
+ public Integer first() { return sortedSet.first(); }
|
|
+ public Integer last() { return sortedSet.last(); }
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
|
|
+ public IntSortedSet headSet( final Integer to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
|
|
+ public IntSortedSet tailSet( final Integer from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet unmodifiable( final IntSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
|
|
new file mode 100644
|
|
index 0000000..71ac087
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
|
|
@@ -0,0 +1,91 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ */
|
|
+public interface IntStack extends Stack<Integer> {
|
|
+ /**
|
|
+ * @see Stack#push(Object)
|
|
+ */
|
|
+ void push( int k );
|
|
+ /**
|
|
+ * @see Stack#pop()
|
|
+ */
|
|
+ int popInt();
|
|
+ /**
|
|
+ * @see Stack#top()
|
|
+ */
|
|
+ int topInt();
|
|
+ /**
|
|
+ * @see Stack#peek(int)
|
|
+ */
|
|
+ int peekInt( int i );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/package.html b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
|
|
new file mode 100644
|
|
index 0000000..7fe95f1
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
|
|
@@ -0,0 +1,12 @@
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
+<html>
|
|
+ <head>
|
|
+ <title>fastutil</title>
|
|
+ </head>
|
|
+
|
|
+ <body>
|
|
+
|
|
+ <P>Provides type-specific classes for integer elements or keys.
|
|
+
|
|
+ </body>
|
|
+</html>
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000..3ef4991
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
|
|
@@ -0,0 +1,150 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class providing basic methods for functions implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>This class handles directly a default return
|
|
+ * value (including {@linkplain #defaultReturnValue() methods to access
|
|
+ * it}). Instances of classes inheriting from this class have just to return
|
|
+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
|
|
+ * is serialized.
|
|
+ *
|
|
+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
|
|
+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractLong2ObjectFunction <V> implements Long2ObjectFunction <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractLong2ObjectFunction() {}
|
|
+ /**
|
|
+ * The default return value for <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code>.
|
|
+ */
|
|
+ protected V defRetValue;
|
|
+ public void defaultReturnValue( final V rv ) {
|
|
+ defRetValue = rv;
|
|
+ }
|
|
+ public V defaultReturnValue() {
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public V put( long key, V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public V remove( long key ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public void clear() {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean containsKey( final Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return containsKey( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V get( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ return containsKey( k ) ? (get( k )) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ *
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final long k = ((ok).longValue());
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = put( k, (ov) );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V remove( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = remove( k );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000..1b2c09f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
|
|
@@ -0,0 +1,271 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for maps implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
|
|
+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
|
|
+ * is particularly useful for those classes that do not implement their own
|
|
+ * entries (e.g., most immutable maps).
|
|
+ */
|
|
+public abstract class AbstractLong2ObjectMap <V> extends AbstractLong2ObjectFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractLong2ObjectMap() {}
|
|
+ /** Checks whether the given value is contained in {@link #values()}. */
|
|
+ public boolean containsValue( Object v ) {
|
|
+ return values().contains( v );
|
|
+ }
|
|
+ /** Checks whether the given value is contained in {@link #keySet()}. */
|
|
+ public boolean containsKey( long k ) {
|
|
+ return keySet().contains( k );
|
|
+ }
|
|
+ /** Puts all pairs in the given map.
|
|
+ * If the map implements the interface of this map,
|
|
+ * it uses the faster iterators.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","deprecation"})
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ int n = m.size();
|
|
+ final Iterator<? extends Map.Entry<? extends Long,? extends V>> i = m.entrySet().iterator();
|
|
+ if (m instanceof Long2ObjectMap) {
|
|
+ Long2ObjectMap.Entry <? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = (Long2ObjectMap.Entry <? extends V>)i.next();
|
|
+ put(e.getLongKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Map.Entry<? extends Long,? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = i.next();
|
|
+ put(e.getKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
|
|
+ * that do not have entries on their own (e.g., most immutable maps).
|
|
+ *
|
|
+ * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
|
|
+ * would not be reflected in the base map.
|
|
+ */
|
|
+ public static class BasicEntry <V> implements Long2ObjectMap.Entry <V> {
|
|
+ protected long key;
|
|
+ protected V value;
|
|
+ public BasicEntry( final Long key, final V value ) {
|
|
+ this.key = ((key).longValue());
|
|
+ this.value = (value);
|
|
+ }
|
|
+ public BasicEntry( final long key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue( final V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (key) == (((((Long)(e.getKey())).longValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "->" + value;
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public LongSet keySet() {
|
|
+ return new AbstractLongSet () {
|
|
+ public boolean contains( final long k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractLong2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectMap.this.clear(); }
|
|
+ public LongIterator iterator() {
|
|
+ return new AbstractLongIterator () {
|
|
+ final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public long nextLong() { return ((Long2ObjectMap.Entry <V>)i.next()).getLongKey(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the values of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new AbstractObjectCollection <V>() {
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractLong2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectMap.this.clear(); }
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new AbstractObjectIterator <V>() {
|
|
+ final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V next() { return ((Long2ObjectMap.Entry <V>)i.next()).getValue(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() {
|
|
+ return (ObjectSet)long2ObjectEntrySet();
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * The hash code of a map is computed by summing the hash codes of its entries.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ while( n-- != 0 ) h += i.next().hashCode();
|
|
+ return h;
|
|
+ }
|
|
+ public boolean equals(Object o) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != size() ) return false;
|
|
+ return entrySet().containsAll( m.entrySet() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ int n = size();
|
|
+ Long2ObjectMap.Entry <V> e;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ e = (Long2ObjectMap.Entry <V>)i.next();
|
|
+ s.append(String.valueOf(e.getLongKey()));
|
|
+ s.append("=>");
|
|
+ if (this == e.getValue()) s.append("(this map)"); else
|
|
+ s.append(String.valueOf(e.getValue()));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000..3b5ca83
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
|
|
@@ -0,0 +1,193 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
|
|
+public abstract class AbstractLong2ObjectSortedMap <V> extends AbstractLong2ObjectMap <V> implements Long2ObjectSortedMap <V> {
|
|
+ private static final long serialVersionUID = -1773560792952436569L;
|
|
+ protected AbstractLong2ObjectSortedMap() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( final Long to ) {
|
|
+ return headMap( ((to).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( final Long from ) {
|
|
+ return tailMap( ((from).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) {
|
|
+ return subMap( ((from).longValue()), ((to).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() {
|
|
+ return (Long.valueOf(firstLongKey()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() {
|
|
+ return (Long.valueOf(lastLongKey()));
|
|
+ }
|
|
+ /** Returns a type-specific-sorted-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public LongSortedSet keySet() {
|
|
+ return new KeySet();
|
|
+ }
|
|
+ /** A wrapper exhibiting the keys of a map. */
|
|
+ protected class KeySet extends AbstractLongSortedSet {
|
|
+ public boolean contains( final long k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
|
|
+ public LongComparator comparator() { return AbstractLong2ObjectSortedMap.this.comparator(); }
|
|
+ public long firstLong() { return firstLongKey(); }
|
|
+ public long lastLong() { return lastLongKey(); }
|
|
+ public LongSortedSet headSet( final long to ) { return headMap( to ).keySet(); }
|
|
+ public LongSortedSet tailSet( final long from ) { return tailMap( from ).keySet(); }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return subMap( from, to ).keySet(); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
|
|
+ public LongBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on keys.
|
|
+ *
|
|
+ * <P>To provide an iterator on keys, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class KeySetIterator <V> extends AbstractLongBidirectionalIterator {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
|
|
+ public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public long nextLong() { return ((i.next().getKey()).longValue()); };
|
|
+ public long previousLong() { return ((i.previous().getKey()).longValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ }
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new ValuesCollection();
|
|
+ }
|
|
+ /** A wrapper exhibiting the values of a map. */
|
|
+ protected class ValuesCollection extends AbstractObjectCollection <V> {
|
|
+ public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on values.
|
|
+ *
|
|
+ * <P>To provide an iterator on values, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
|
|
+ public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public V next() { return (i.next().getValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() {
|
|
+ return (ObjectSortedSet)long2ObjectEntrySet();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..63ee559
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
|
|
@@ -0,0 +1,95 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractLongBidirectionalIterator extends AbstractLongIterator implements LongBidirectionalIterator {
|
|
+ protected AbstractLongBidirectionalIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public long previousLong() { return previous().longValue(); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Long previous() { return Long.valueOf( previousLong() ); }
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousLong();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
|
|
new file mode 100644
|
|
index 0000000..fdd3120
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
|
|
@@ -0,0 +1,271 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractLongCollection extends AbstractCollection<Long> implements LongCollection {
|
|
+ protected AbstractLongCollection() {}
|
|
+ public long[] toArray( long a[] ) {
|
|
+ return toLongArray( a );
|
|
+ }
|
|
+ public long[] toLongArray() {
|
|
+ return toLongArray( null );
|
|
+ }
|
|
+ public long[] toLongArray( long a[] ) {
|
|
+ if ( a == null || a.length < size() ) a = new long[ size() ];
|
|
+ LongIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given type-specific collection to this collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ final LongIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.nextLong() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( LongCollection c ) {
|
|
+ final LongIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( ! contains( i.nextLong() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final LongIterator i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.nextLong() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final LongIterator i = c.iterator();
|
|
+ while( n-- != 0 ) if ( rem( i.nextLong() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends Long> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract LongIterator iterator();
|
|
+ /** Delegates to the type-specific <code>rem()</code> method. */
|
|
+ public boolean remove( Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return rem( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean add( final Long o ) {
|
|
+ return add( o.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean rem( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return contains( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ final LongIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() ) if ( k == iterator.nextLong() ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ public boolean rem( final long k ) {
|
|
+ final LongIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() )
|
|
+ if ( k == iterator.nextLong() ) {
|
|
+ iterator.remove();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final LongIterator i = iterator();
|
|
+ int n = size();
|
|
+ long k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextLong();
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
|
|
new file mode 100644
|
|
index 0000000..f437517
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
|
|
@@ -0,0 +1,87 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
|
|
+ *
|
|
+ * <P>To create a type-specific comparator you need both a method comparing
|
|
+ * primitive types and a method comparing objects. However, if you have the
|
|
+ * first one you can just inherit from this class and get for free the second
|
|
+ * one.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ */
|
|
+public abstract class AbstractLongComparator implements LongComparator , java.io.Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ protected AbstractLongComparator() {}
|
|
+ public int compare( Long ok1, Long ok2 ) {
|
|
+ return compare( ok1.longValue(), ok2.longValue() );
|
|
+ }
|
|
+ public abstract int compare( long k1, long k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
|
|
new file mode 100644
|
|
index 0000000..610c855
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
|
|
@@ -0,0 +1,100 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractLongIterator implements LongIterator {
|
|
+ protected AbstractLongIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public long nextLong() { return next().longValue(); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long next() { return Long.valueOf( nextLong() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextLong();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
|
|
new file mode 100644
|
|
index 0000000..d4f51d2
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
|
|
@@ -0,0 +1,577 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractLongList extends AbstractLongCollection implements LongList , LongStack {
|
|
+ protected AbstractLongList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public long removeLong( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public long set( final int index, final long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends Long> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends Long> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends Long> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public LongListIterator iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public LongListIterator listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractLongList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = pos++ ); }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ AbstractLongList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractLongList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractLongList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final long k ) {
|
|
+ final LongListIterator i = listIterator();
|
|
+ long e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.nextLong();
|
|
+ if ( ( (k) == (e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final long k ) {
|
|
+ LongListIterator i = listIterator( size() );
|
|
+ long e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previousLong();
|
|
+ if ( ( (k) == (e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (0) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new LongSubList ( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ LongListIterator i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.nextLong();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final long a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final long a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final long a[], int offset, int length ) {
|
|
+ LongListIterator i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.nextLong();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ if ( l instanceof LongList ) {
|
|
+ final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
|
|
+ while( s-- != 0 ) if ( i1.nextLong() != i2.nextLong() ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final List<? extends Long> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof LongList ) {
|
|
+ final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
|
|
+ int r;
|
|
+ long e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.nextLong();
|
|
+ e2 = i2.nextLong();
|
|
+ if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends Long> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super Long>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ LongIterator i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ long k = i.nextLong();
|
|
+ h = 31 * h + it.unimi.dsi.fastutil.HashCommon.long2int(k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( long o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public long popLong() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return removeLong( size() - 1 );
|
|
+ }
|
|
+ public long topLong() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return getLong( size() - 1 );
|
|
+ }
|
|
+ public long peekLong( int i ) {
|
|
+ return getLong( size() - 1 - i );
|
|
+ }
|
|
+ public boolean rem( long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeLong( index );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to <code>rem()</code>. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final LongCollection c ) {
|
|
+ return addAll( index, (Collection<? extends Long>)c );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ return addAll( index, (LongCollection)l );
|
|
+ }
|
|
+ public boolean addAll( final LongCollection c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ public boolean addAll( final LongList l ) {
|
|
+ return addAll( size(), l );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( final int index, final Long ok ) {
|
|
+ add( index, ok.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long set( final int index, final Long ok ) {
|
|
+ return (Long.valueOf(set( index, ok.longValue() )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long get( final int index ) {
|
|
+ return (Long.valueOf(getLong( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int indexOf( final Object ok) {
|
|
+ return indexOf( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int lastIndexOf( final Object ok ) {
|
|
+ return lastIndexOf( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long remove( final int index ) {
|
|
+ return (Long.valueOf(removeLong( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Long o ) {
|
|
+ push( o.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long pop() {
|
|
+ return Long.valueOf( popLong() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long top() {
|
|
+ return Long.valueOf( topLong() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long peek( int i ) {
|
|
+ return Long.valueOf( peekLong( i ) );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final LongIterator i = iterator();
|
|
+ int n = size();
|
|
+ long k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextLong();
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class LongSubList extends AbstractLongList implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final LongList l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public LongSubList( final LongList l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public long getLong( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.getLong( from + index );
|
|
+ }
|
|
+ public long removeLong( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.removeLong( from + index );
|
|
+ }
|
|
+ public long set( int index, long k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final long[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getLong( from + ( last = pos++ ) ); }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getLong( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new LongSubList ( this, from, to );
|
|
+ }
|
|
+ public boolean rem( long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ to--;
|
|
+ l.removeLong( from + index );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ ensureIndex( index );
|
|
+ to += l.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = this.l.addAll( from + index, l );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return this.l.addAll( from + index, l );
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
|
|
new file mode 100644
|
|
index 0000000..963a9cd
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
|
|
@@ -0,0 +1,92 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractLongListIterator extends AbstractLongBidirectionalIterator implements LongListIterator {
|
|
+ protected AbstractLongListIterator() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void set( Long ok ) { set( ok.longValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( Long ok ) { add( ok.longValue() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( long k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( long k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..f7606fb
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
|
|
@@ -0,0 +1,95 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
|
|
+/** An abstract class providing basic methods for priority queues implementing a type-specific interface.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractLongPriorityQueue extends AbstractPriorityQueue<Long> implements java.io.Serializable, LongPriorityQueue {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public void enqueue( final Long x ) { enqueue( x.longValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long dequeue() { return (Long.valueOf(dequeueLong())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() { return (Long.valueOf(firstLong())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() { return (Long.valueOf(lastLong())); }
|
|
+ /** Throws an {@link UnsupportedOperationException}. */
|
|
+ public long lastLong() { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
|
|
new file mode 100644
|
|
index 0000000..91c6eef
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
|
|
@@ -0,0 +1,115 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractLongSet extends AbstractLongCollection implements Cloneable, LongSet {
|
|
+ protected AbstractLongSet() {}
|
|
+ public abstract LongIterator iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ LongIterator i = iterator();
|
|
+ long k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.nextLong(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += it.unimi.dsi.fastutil.HashCommon.long2int(k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to <code>remove()</code>.
|
|
+ *
|
|
+ * @param k the element to be removed.
|
|
+ * @return true if the set was modified.
|
|
+ */
|
|
+ public boolean rem( long k ) {
|
|
+ return remove( k );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return remove( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..84bd619
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
|
|
@@ -0,0 +1,110 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractLongSortedSet extends AbstractLongSet implements LongSortedSet {
|
|
+ protected AbstractLongSortedSet() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet headSet( final Long to ) {
|
|
+ return headSet( to.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet tailSet( final Long from ) {
|
|
+ return tailSet( from.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) {
|
|
+ return subSet( from.longValue(), to.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() {
|
|
+ return (Long.valueOf(firstLong()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() {
|
|
+ return (Long.valueOf(lastLong()));
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract LongBidirectionalIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
|
|
new file mode 100644
|
|
index 0000000..23ece85
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
|
|
@@ -0,0 +1,346 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A simple, brute-force implementation of a map based on two parallel backing arrays.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
|
|
+ */
|
|
+public class Long2ObjectArrayMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The keys (valid up to {@link #size}, excluded). */
|
|
+ private transient long[] key;
|
|
+ /** The values (parallel to {@link #key}). */
|
|
+ private transient Object[] value;
|
|
+ /** The number of valid entries in {@link #key} and {@link #value}. */
|
|
+ private int size;
|
|
+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final long[] key, final Object[] value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ size = key.length;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ }
|
|
+ /** Creates a new empty array map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap() {
|
|
+ this.key = LongArrays.EMPTY_ARRAY;
|
|
+ this.value = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array map of given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final int capacity ) {
|
|
+ this.key = new long[ capacity ];
|
|
+ this.value = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ * @param size the number of valid elements in <code>key</code> and <code>value</code>.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final long[] key, final Object[] value, final int size ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ this.size = size;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
|
|
+ }
|
|
+ private final class EntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ @Override
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
|
|
+ int curr = -1, next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return new AbstractLong2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
|
|
+ int next = 0, curr = -1;
|
|
+ final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ entry.key = key[ curr = next ];
|
|
+ entry.value = (V) value[ next++ ];
|
|
+ return entry;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( Object o ) {
|
|
+ if ( ! ( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ return Long2ObjectArrayMap.this.containsKey( k ) && ( (Long2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Long2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Override
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ final int oldPos = Long2ObjectArrayMap.this.findKey( k );
|
|
+ if ( oldPos == -1 || ! ( (v) == null ? (Long2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Long2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( Long2ObjectArrayMap.this.key, oldPos + 1, Long2ObjectArrayMap.this.key, oldPos, tail );
|
|
+ System.arraycopy( Long2ObjectArrayMap.this.value, oldPos + 1, Long2ObjectArrayMap.this.value, oldPos, tail );
|
|
+ Long2ObjectArrayMap.this.size--;
|
|
+ Long2ObjectArrayMap.this.value[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ return new EntrySet();
|
|
+ }
|
|
+ private int findKey( final long k ) {
|
|
+ final long[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V get( final long k ) {
|
|
+ final long[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ value[ i ] = null;
|
|
+ }
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsKey( final long k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsValue( Object v ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V put( long k, V v ) {
|
|
+ final int oldKey = findKey( k );
|
|
+ if ( oldKey != -1 ) {
|
|
+ final V oldValue = (V) value[ oldKey ];
|
|
+ value[ oldKey ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ if ( size == key.length ) {
|
|
+ final long[] newKey = new long[ size == 0 ? 2 : size * 2 ];
|
|
+ final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ newKey[ i ] = key[ i ];
|
|
+ newValue[ i ] = value[ i ];
|
|
+ }
|
|
+ key = newKey;
|
|
+ value = newValue;
|
|
+ }
|
|
+ key[ size ] = k;
|
|
+ value[ size ] = v;
|
|
+ size++;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V remove( final long k ) {
|
|
+ final int oldPos = findKey( k );
|
|
+ if ( oldPos == -1 ) return defRetValue;
|
|
+ final V oldValue = (V) value[ oldPos ];
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( key, oldPos + 1, key, oldPos, tail );
|
|
+ System.arraycopy( value, oldPos + 1, value, oldPos, tail );
|
|
+ size--;
|
|
+ value[ size ] = null;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @Override
|
|
+ public LongSet keySet() {
|
|
+ return new LongArraySet ( key, size );
|
|
+ }
|
|
+ @Override
|
|
+ public ObjectCollection <V> values() {
|
|
+ return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectArrayMap <V> clone() {
|
|
+ Long2ObjectArrayMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectArrayMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ s.writeLong( key[ i ] );
|
|
+ s.writeObject( value[ i ] );
|
|
+ }
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ key = new long[ size ];
|
|
+ value = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ key[ i ] = s.readLong();
|
|
+ value[ i ] = s.readObject();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000..be0234e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
|
|
@@ -0,0 +1,137 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Function;
|
|
+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
|
|
+ * a key. Rather, they return a {@linkplain #defaultReturnValue() default
|
|
+ * return value}, which is set to 0 cast to the return type (<code>false</code>
|
|
+ * for booleans) at creation, but can be changed using the
|
|
+ * <code>defaultReturnValue()</code> method.
|
|
+ *
|
|
+ * <P>For uniformity reasons, even maps returning objects implement the default
|
|
+ * return value (of course, in this case the default return value is
|
|
+ * initialized to <code>null</code>).
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
|
|
+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
|
|
+ * that standard versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> for maps with primitive-type values <em>return
|
|
+ * <code>null</code> to denote missing keys</em> rather than wrap the default
|
|
+ * return value in an object (of course, for maps with object keys and values
|
|
+ * this is not possible, as there is no type-specific version).
|
|
+ *
|
|
+ * @see Function
|
|
+ */
|
|
+public interface Long2ObjectFunction <V> extends Function<Long, V> {
|
|
+ /** Adds a pair to the map.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#put(Object,Object)
|
|
+ */
|
|
+ V put( long key, V value );
|
|
+ /** Returns the value to which the given key is mapped.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#get(Object)
|
|
+ */
|
|
+ V get( long key );
|
|
+ /** Removes the mapping with the given key.
|
|
+ * @param key the key.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#remove(Object)
|
|
+ */
|
|
+ V remove( long key );
|
|
+ /**
|
|
+ * @see Function#containsKey(Object)
|
|
+ */
|
|
+ boolean containsKey( long key );
|
|
+ /** Sets the default return value.
|
|
+ *
|
|
+ * This value must be returned by type-specific versions of
|
|
+ * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
|
|
+ * denote that the map does not contain the specified key. It must be
|
|
+ * 0/<code>false</code>/<code>null</code> by default.
|
|
+ *
|
|
+ * @param rv the new default return value.
|
|
+ * @see #defaultReturnValue()
|
|
+ */
|
|
+ void defaultReturnValue( V rv );
|
|
+ /** Gets the default return value.
|
|
+ *
|
|
+ * @return the current default return value.
|
|
+ */
|
|
+ V defaultReturnValue();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
|
|
new file mode 100644
|
|
index 0000000..5afe8fb
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
|
|
@@ -0,0 +1,224 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with type-specific functions.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Function
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectFunctions {
|
|
+ private Long2ObjectFunctions() {}
|
|
+ /** An immutable class representing an empty type-specific function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class EmptyFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyFunction() {}
|
|
+ public V get( final long k ) { return (null); }
|
|
+ public boolean containsKey( final long k ) { return false; }
|
|
+ public V defaultReturnValue() { return (null); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return null; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ private Object readResolve() { return EMPTY_FUNCTION; }
|
|
+ public Object clone() { return EMPTY_FUNCTION; }
|
|
+ }
|
|
+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
|
|
+ /** An immutable class representing a type-specific singleton function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class Singleton <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final long key;
|
|
+ protected final V value;
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ public boolean containsKey( final long k ) { return ( (key) == (k) ); }
|
|
+ public V get( final long k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectFunction <V> singleton( final long key, V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectFunction <V> singleton( final Long key, final V value ) {
|
|
+ return new Singleton <V>( ((key).longValue()), (value) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for functions. */
|
|
+ public static class SynchronizedFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectFunction <V> function;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedFunction( final Long2ObjectFunction <V> f, final Object sync ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedFunction( final Long2ObjectFunction <V> f ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return function.size(); } }
|
|
+ public boolean containsKey( final long k ) { synchronized( sync ) { return function.containsKey( k ); } }
|
|
+ public V defaultReturnValue() { synchronized( sync ) { return function.defaultReturnValue(); } }
|
|
+ public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { function.defaultReturnValue( defRetValue ); } }
|
|
+ public V put( final long k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
|
|
+ public void clear() { synchronized( sync ) { function.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return function.toString(); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long k, final V v ) { synchronized( sync ) { return function.put( k, v ); } }
|
|
+ @Override
|
|
+ public V get( final Object k ) { synchronized( sync ) { return function.get( k ); } }
|
|
+ @Override
|
|
+ public V remove( final Object k ) { synchronized( sync ) { return function.remove( k ); } }
|
|
+ @Override
|
|
+ public V remove( final long k ) { synchronized( sync ) { return function.remove( k ); } }
|
|
+ @Override
|
|
+ public V get( final long k ) { synchronized( sync ) { return function.get( k ); } }
|
|
+ public boolean containsKey( final Object ok ) { synchronized( sync ) { return function.containsKey( ok ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific function backed by the given type-specific function.
|
|
+ *
|
|
+ * @param f the function to be wrapped in a synchronized function.
|
|
+ * @return a synchronized view of the specified function.
|
|
+ * @see java.util.Collections#synchronizedMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectFunction <V> synchronize( final Long2ObjectFunction <V> f ) { return new SynchronizedFunction <V>( f ); }
|
|
+ /** Returns a synchronized type-specific function backed by the given type-specific function, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param f the function to be wrapped in a synchronized function.
|
|
+ * @param sync an object that will be used to synchronize the access to the function.
|
|
+ * @return a synchronized view of the specified function.
|
|
+ * @see java.util.Collections#synchronizedMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectFunction <V> synchronize( final Long2ObjectFunction <V> f, final Object sync ) { return new SynchronizedFunction <V>( f, sync ); }
|
|
+ /** An unmodifiable wrapper class for functions. */
|
|
+ public static class UnmodifiableFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectFunction <V> function;
|
|
+ protected UnmodifiableFunction( final Long2ObjectFunction <V> f ) {
|
|
+ if ( f == null ) throw new NullPointerException();
|
|
+ this.function = f;
|
|
+ }
|
|
+ public int size() { return function.size(); }
|
|
+ public boolean containsKey( final long k ) { return function.containsKey( k ); }
|
|
+ public V defaultReturnValue() { return function.defaultReturnValue(); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ public V put( final long k, final V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return function.toString(); }
|
|
+ @Override
|
|
+ public V remove( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final long k ) { return function.get( k ); }
|
|
+ public boolean containsKey( final Object ok ) { return function.containsKey( ok ); }
|
|
+ @Override
|
|
+ public V remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return function.get( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific function backed by the given type-specific function.
|
|
+ *
|
|
+ * @param f the function to be wrapped in an unmodifiable function.
|
|
+ * @return an unmodifiable view of the specified function.
|
|
+ * @see java.util.Collections#unmodifiableMap(java.util.Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectFunction <V> unmodifiable( final Long2ObjectFunction <V> f ) { return new UnmodifiableFunction <V>( f ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000..d221ba0
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
|
|
@@ -0,0 +1,1444 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+/** A type-specific linked hash map with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
|
|
+ * have been added to the map (addition of pairs whose key is already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted map, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first key
|
|
+ * in iteration order with {@code firstKey()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
|
|
+ * contract because all submap methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class using are type-specific
|
|
+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is a key of the map</em>, or
|
|
+ * a {@link NoSuchElementException} exception will be thrown.
|
|
+ * If, however, the provided element is not the first or last key in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire key set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectLinkedOpenHashMap <V> extends AbstractLong2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastSortedEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectLinkedOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ private V setValue( final int pos, final V v ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Removes the mapping associated with the first key in iteration order.
|
|
+ * @return the value previously associated with the first key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeFirst() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ /** Removes the mapping associated with the last key in iteration order.
|
|
+ * @return the value previously associated with the last key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeLast() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToFirst( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToLast( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToFirst( final long k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToLast( final long k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * <P>This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first key of this map in iteration order.
|
|
+ *
|
|
+ * @return the first key in iteration order.
|
|
+ */
|
|
+ public long firstLongKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last key of this map in iteration order.
|
|
+ *
|
|
+ * @return the last key in iteration order.
|
|
+ */
|
|
+ public long lastLongKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ public Long2ObjectSortedMap <V> tailMap( long from ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectSortedMap <V> headMap( long to ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectSortedMap <V> subMap( long from, long to ) { throw new UnsupportedOperationException(); }
|
|
+ /** A list iterator over a linked map.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
|
|
+ */
|
|
+ private class MapIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
|
|
+ int index = -1;
|
|
+ private MapIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ private MapIterator( final long from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( Long2ObjectLinkedOpenHashMap.this.containsNullKey ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ int pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (from) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return curr;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ Long2ObjectLinkedOpenHashMap.this.containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public EntryIterator() {}
|
|
+ public EntryIterator( long from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ return entry = new MapEntry( previousEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
|
|
+ final MapEntry entry = new MapEntry();
|
|
+ public FastEntryIterator() {}
|
|
+ public FastEntryIterator( long from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ entry.index = previousEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSortedSet<Long2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public Comparator<? super Long2ObjectMap.Entry <V> > comparator() { return null; }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > subSet( Long2ObjectMap.Entry <V> fromElement, Long2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > headSet( Long2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > tailSet( Long2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectMap.Entry <V> first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Long2ObjectLinkedOpenHashMap.this.first );
|
|
+ }
|
|
+ public Long2ObjectMap.Entry <V> last() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Long2ObjectLinkedOpenHashMap.this.last );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Long2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator( final Long2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getLongKey() );
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( final Long2ObjectMap.Entry <V> from ) {
|
|
+ return new FastEntryIterator( from.getLongKey() );
|
|
+ }
|
|
+ }
|
|
+ public FastSortedEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongListIterator {
|
|
+ public KeyIterator( final long k ) { super( k ); }
|
|
+ public long previousLong() { return key[ previousEntry() ]; }
|
|
+ public void set( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long previous() { return (Long.valueOf(key[ previousEntry() ])); }
|
|
+ public void set( Long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSortedSet {
|
|
+ public LongListIterator iterator( final long from ) {
|
|
+ return new KeyIterator( from );
|
|
+ }
|
|
+ public LongListIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectLinkedOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public long firstLong() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ public long lastLong() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ final public LongSortedSet tailSet( long from ) { throw new UnsupportedOperationException(); }
|
|
+ final public LongSortedSet headSet( long to ) { throw new UnsupportedOperationException(); }
|
|
+ final public LongSortedSet subSet( long from, long to ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public LongSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
|
|
+ public V previous() { return value[ previousEntry() ]; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectLinkedOpenHashMap <V> clone() {
|
|
+ Long2ObjectLinkedOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectLinkedOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000..afbb18d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
|
|
@@ -0,0 +1,151 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Map;
|
|
+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
|
|
+ *
|
|
+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
|
|
+ *
|
|
+ * <P>A submap or subset may or may not have an
|
|
+ * independent default return value (which however must be initialized to the
|
|
+ * default return value of the originator).
|
|
+ *
|
|
+ * @see Map
|
|
+ */
|
|
+public interface Long2ObjectMap <V> extends Long2ObjectFunction <V>, Map<Long,V> {
|
|
+ /** An entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastEntrySet <V> extends ObjectSet<Long2ObjectMap.Entry <V> > {
|
|
+ /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
|
|
+ */
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator();
|
|
+ }
|
|
+ /** Returns a set view of the mappings contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
|
|
+ *
|
|
+ * @return a set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSet<Map.Entry<Long, V>> entrySet();
|
|
+ /** Returns a type-specific set view of the mappings contained in this map.
|
|
+ *
|
|
+ * <p>This method is necessary because there is no inheritance along
|
|
+ * type parameters: it is thus impossible to strengthen {@link #entrySet()}
|
|
+ * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
|
|
+ * of type-specific entries (the latter makes it possible to
|
|
+ * access keys and values with type-specific methods).
|
|
+ *
|
|
+ * @return a type-specific set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
|
|
+ /** Returns a set view of the keys contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
|
|
+ *
|
|
+ * @return a set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ LongSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * @see java.util.Map.Entry
|
|
+ */
|
|
+ interface Entry <V> extends Map.Entry <Long,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ Long getKey();
|
|
+ /**
|
|
+ * @see java.util.Map.Entry#getKey()
|
|
+ */
|
|
+ long getLongKey();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
|
|
new file mode 100644
|
|
index 0000000..9047158
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
|
|
@@ -0,0 +1,312 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import java.util.Map;
|
|
+/** A class providing static methods and objects that do useful things with type-specific maps.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Maps
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectMaps {
|
|
+ private Long2ObjectMaps() {}
|
|
+ /** An immutable class representing an empty type-specific map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class EmptyMap <V> extends Long2ObjectFunctions.EmptyFunction <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyMap() {}
|
|
+ public boolean containsValue( final Object v ) { return false; }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
|
|
+
|
|
+ public LongSet keySet() { return LongSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_MAP; }
|
|
+ public Object clone() { return EMPTY_MAP; }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ return ((Map<?,?>)o).isEmpty();
|
|
+ }
|
|
+ public String toString() { return "{}"; }
|
|
+ }
|
|
+ /** An empty type-specific map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
|
|
+ /** Return an empty map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Long2ObjectMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Long2ObjectFunctions.Singleton <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
|
|
+ protected transient LongSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ super( key, value );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
|
|
+ public LongSet keySet() { if ( keys == null ) keys = LongSets.singleton( key ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
|
|
+ protected class SingletonEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() { return (Long.valueOf(Singleton.this.key)); }
|
|
+ public V getValue() { return (Singleton.this.value); }
|
|
+ public long getLongKey() { return Singleton.this.key; }
|
|
+ public V setValue( final V value ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (Singleton.this.key) == (((((Long)(e.getKey())).longValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
|
|
+ public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
|
|
+ }
|
|
+ public boolean isEmpty() { return false; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
|
|
+ public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != 1 ) return false;
|
|
+ return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
|
|
+ }
|
|
+ public String toString() { return "{" + key + "=>" + value + "}"; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectMap <V> singleton( final long key, V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectMap <V> singleton( final Long key, final V value ) {
|
|
+ return new Singleton <V>( ((key).longValue()), (value) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for maps. */
|
|
+ public static class SynchronizedMap <V> extends Long2ObjectFunctions.SynchronizedFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectMap <V> map;
|
|
+ protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
|
|
+ protected transient LongSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected SynchronizedMap( final Long2ObjectMap <V> m, final Object sync ) {
|
|
+ super( m, sync );
|
|
+ this.map = m;
|
|
+ }
|
|
+ protected SynchronizedMap( final Long2ObjectMap <V> m ) {
|
|
+ super( m );
|
|
+ this.map = m;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return map.size(); } }
|
|
+ public boolean containsKey( final long k ) { synchronized( sync ) { return map.containsKey( k ); } }
|
|
+ public boolean containsValue( final Object v ) { synchronized( sync ) { return map.containsValue( v ); } }
|
|
+ public V defaultReturnValue() { synchronized( sync ) { return map.defaultReturnValue(); } }
|
|
+ public void defaultReturnValue( final V defRetValue ) { synchronized( sync ) { map.defaultReturnValue( defRetValue ); } }
|
|
+ public V put( final long k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
|
|
+ //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { synchronized( sync ) { map.putAll( c ); } }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { synchronized( sync ) { map.putAll( m ); } }
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.synchronize( map.long2ObjectEntrySet(), sync ); return entries; }
|
|
+ public LongSet keySet() { if ( keys == null ) keys = LongSets.synchronize( map.keySet(), sync ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.synchronize( map.values(), sync ); return values; }
|
|
+ public void clear() { synchronized( sync ) { map.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return map.toString(); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long k, final V v ) { synchronized( sync ) { return map.put( k, v ); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final long k ) { synchronized( sync ) { return map.remove( k ); } }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final long k ) { synchronized( sync ) { return map.get( k ); } }
|
|
+ public boolean containsKey( final Object ok ) { synchronized( sync ) { return map.containsKey( ok ); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return map.isEmpty(); } }
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { synchronized( sync ) { return map.entrySet(); } }
|
|
+ public int hashCode() { synchronized( sync ) { return map.hashCode(); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return map.equals( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific map backed by the given type-specific map.
|
|
+ *
|
|
+ * @param m the map to be wrapped in a synchronized map.
|
|
+ * @return a synchronized view of the specified map.
|
|
+ * @see java.util.Collections#synchronizedMap(Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectMap <V> synchronize( final Long2ObjectMap <V> m ) { return new SynchronizedMap <V>( m ); }
|
|
+ /** Returns a synchronized type-specific map backed by the given type-specific map, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param m the map to be wrapped in a synchronized map.
|
|
+ * @param sync an object that will be used to synchronize the access to the map.
|
|
+ * @return a synchronized view of the specified map.
|
|
+ * @see java.util.Collections#synchronizedMap(Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectMap <V> synchronize( final Long2ObjectMap <V> m, final Object sync ) { return new SynchronizedMap <V>( m, sync ); }
|
|
+ /** An unmodifiable wrapper class for maps. */
|
|
+ public static class UnmodifiableMap <V> extends Long2ObjectFunctions.UnmodifiableFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectMap <V> map;
|
|
+ protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
|
|
+ protected transient LongSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected UnmodifiableMap( final Long2ObjectMap <V> m ) {
|
|
+ super( m );
|
|
+ this.map = m;
|
|
+ }
|
|
+ public int size() { return map.size(); }
|
|
+ public boolean containsKey( final long k ) { return map.containsKey( k ); }
|
|
+ public boolean containsValue( final Object v ) { return map.containsValue( v ); }
|
|
+ public V defaultReturnValue() { throw new UnsupportedOperationException(); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ public V put( final long k, final V v ) { throw new UnsupportedOperationException(); }
|
|
+ //public void putAll( final MAP KEY_VALUE_EXTENDS_GENERIC c ) { throw new UnsupportedOperationException(); }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.unmodifiable( map.long2ObjectEntrySet() ); return entries; }
|
|
+ public LongSet keySet() { if ( keys == null ) keys = LongSets.unmodifiable( map.keySet() ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) return ObjectCollections.unmodifiable( map.values() ); return values; }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return map.toString(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final long k ) { return map.get( k ); }
|
|
+ public boolean containsKey( final Object ok ) { return map.containsKey( ok ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V get( final Object k ) { return map.get( k ); }
|
|
+ public boolean isEmpty() { return map.isEmpty(); }
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { return ObjectSets.unmodifiable( map.entrySet() ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific map backed by the given type-specific map.
|
|
+ *
|
|
+ * @param m the map to be wrapped in an unmodifiable map.
|
|
+ * @return an unmodifiable view of the specified map.
|
|
+ * @see java.util.Collections#unmodifiableMap(Map)
|
|
+ */
|
|
+ public static <V> Long2ObjectMap <V> unmodifiable( final Long2ObjectMap <V> m ) { return new UnmodifiableMap <V>( m ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
|
|
new file mode 100644
|
|
index 0000000..547fcbf
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
|
|
@@ -0,0 +1,922 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectOpenCustomHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The hash strategy of this custom map. */
|
|
+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( k.length, f, strategy );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash map.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( strategy.equals( (key[ index ]), (((e.getKey()).longValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Long2ObjectOpenCustomHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final long key[] = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final long k = wrapped.getLong( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Long2ObjectOpenCustomHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Long2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return ( Long2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSet {
|
|
+ public LongIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectOpenCustomHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public LongSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenCustomHashMap <V> clone() {
|
|
+ Long2ObjectOpenCustomHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectOpenCustomHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = ( strategy.hashCode(key[ i ]) );
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000..9666263
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
|
|
@@ -0,0 +1,901 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectOpenHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final long[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final long[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Long2ObjectOpenHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final long key[] = Long2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final long k = wrapped.getLong( - pos - 1 );
|
|
+ int p = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Long2ObjectOpenHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Long2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Long2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSet {
|
|
+ public LongIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public LongSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenHashMap <V> clone() {
|
|
+ Long2ObjectOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000..365ebc7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
|
|
@@ -0,0 +1,181 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()}, {@link #values()},
|
|
+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap
|
|
+ */
|
|
+public interface Long2ObjectSortedMap <V> extends Long2ObjectMap <V>, SortedMap<Long, V> {
|
|
+ /** A sorted entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of entry objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Long2ObjectMap.Entry <V> >, FastEntrySet <V> {
|
|
+ /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ */
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( Long2ObjectMap.Entry <V> from );
|
|
+ }
|
|
+ /** Returns a sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Map.Entry<Long, V>> entrySet();
|
|
+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
|
|
+ /** Returns a sorted-set view of the keys contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ LongSortedSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link SortedMap}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
|
|
+ *
|
|
+ * @see SortedMap#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> subMap(Long fromKey, Long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> headMap(Long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> tailMap(Long fromKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> subMap(long fromKey, long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> headMap(long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> tailMap(long fromKey);
|
|
+ /**
|
|
+ * @see SortedMap#firstKey()
|
|
+ */
|
|
+ long firstLongKey();
|
|
+ /**
|
|
+ * @see SortedMap#lastKey()
|
|
+ */
|
|
+ long lastLongKey();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
|
|
new file mode 100644
|
|
index 0000000..1a91791
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
|
|
@@ -0,0 +1,326 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
|
|
+import java.util.Comparator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectSortedMaps {
|
|
+ private Long2ObjectSortedMaps() {}
|
|
+ /** Returns a comparator for entries based on a given comparator on keys.
|
|
+ *
|
|
+ * @param comparator a comparator on keys.
|
|
+ * @return the associated comparator on entries.
|
|
+ */
|
|
+ public static Comparator<? super Map.Entry<Long, ?>> entryComparator( final LongComparator comparator ) {
|
|
+ return new Comparator<Map.Entry<Long, ?>>() {
|
|
+ public int compare( Map.Entry<Long, ?> x, Map.Entry<Long, ?> y ) {
|
|
+ return comparator.compare( x.getKey(), y.getKey() );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class EmptySortedMap <V> extends Long2ObjectMaps.EmptyMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySortedMap() {}
|
|
+ public LongComparator comparator() { return null; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet keySet() { return LongSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { return EMPTY_MAP; }
|
|
+ public long firstLongKey() { throw new NoSuchElementException(); }
|
|
+ public long lastLongKey() { throw new NoSuchElementException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() { return (Long.valueOf(firstLongKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() { return (Long.valueOf(lastLongKey())); }
|
|
+ }
|
|
+ /** An empty sorted map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
|
|
+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty sorted map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Long2ObjectSortedMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Long2ObjectMaps.Singleton <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongComparator comparator;
|
|
+ protected Singleton( final long key, final V value, LongComparator comparator ) {
|
|
+ super( key, value );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ this( key, value, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final long k1, final long k2 ) {
|
|
+ return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ public LongComparator comparator() { return comparator; }
|
|
+
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Long2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
|
|
+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.singleton( key, comparator ); return (LongSortedSet )keys; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
|
|
+ public long firstLongKey() { return key; }
|
|
+ public long lastLongKey() { return key; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() { return (Long.valueOf(firstLongKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() { return (Long.valueOf(lastLongKey())); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> singleton( final Long key, V value ) {
|
|
+ return new Singleton <V>( ((key).longValue()), (value) );
|
|
+ }
|
|
+ /** RETURNS a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @param comparator the comparator to use in the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> singleton( final Long key, V value, LongComparator comparator ) {
|
|
+ return new Singleton <V>( ((key).longValue()), (value), comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> singleton( final long key, final V value ) {
|
|
+ return new Singleton <V>( key, value );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @param comparator the comparator to use in the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><key,value></code>.
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> singleton( final long key, final V value, LongComparator comparator ) {
|
|
+ return new Singleton <V>( key, value, comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted maps. */
|
|
+ public static class SynchronizedSortedMap <V> extends Long2ObjectMaps.SynchronizedMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectSortedMap <V> sortedMap;
|
|
+ protected SynchronizedSortedMap( final Long2ObjectSortedMap <V> m, final Object sync ) {
|
|
+ super( m, sync );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ protected SynchronizedSortedMap( final Long2ObjectSortedMap <V> m ) {
|
|
+ super( m );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ public LongComparator comparator() { synchronized( sync ) { return sortedMap.comparator(); } }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.synchronize( sortedMap.long2ObjectEntrySet(), sync ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
|
|
+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.synchronize( sortedMap.keySet(), sync ); return (LongSortedSet )keys; }
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
|
|
+ public long firstLongKey() { synchronized( sync ) { return sortedMap.firstLongKey(); } }
|
|
+ public long lastLongKey() { synchronized( sync ) { return sortedMap.lastLongKey(); } }
|
|
+ public Long firstKey() { synchronized( sync ) { return sortedMap.firstKey(); } }
|
|
+ public Long lastKey() { synchronized( sync ) { return sortedMap.lastKey(); } }
|
|
+ public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) { return new SynchronizedSortedMap <V>( sortedMap.subMap( from, to ), sync ); }
|
|
+ public Long2ObjectSortedMap <V> headMap( final Long to ) { return new SynchronizedSortedMap <V>( sortedMap.headMap( to ), sync ); }
|
|
+ public Long2ObjectSortedMap <V> tailMap( final Long from ) { return new SynchronizedSortedMap <V>( sortedMap.tailMap( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in a synchronized sorted map.
|
|
+ * @return a synchronized view of the specified sorted map.
|
|
+ * @see java.util.Collections#synchronizedSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> synchronize( final Long2ObjectSortedMap <V> m ) { return new SynchronizedSortedMap <V>( m ); }
|
|
+ /** Returns a synchronized type-specific sorted map backed by the given type-specific sorted map, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in a synchronized sorted map.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted sorted map.
|
|
+ * @return a synchronized view of the specified sorted map.
|
|
+ * @see java.util.Collections#synchronizedSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> synchronize( final Long2ObjectSortedMap <V> m, final Object sync ) { return new SynchronizedSortedMap <V>( m, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted maps. */
|
|
+ public static class UnmodifiableSortedMap <V> extends Long2ObjectMaps.UnmodifiableMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final Long2ObjectSortedMap <V> sortedMap;
|
|
+ protected UnmodifiableSortedMap( final Long2ObjectSortedMap <V> m ) {
|
|
+ super( m );
|
|
+ sortedMap = m;
|
|
+ }
|
|
+ public LongComparator comparator() { return sortedMap.comparator(); }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.unmodifiable( sortedMap.long2ObjectEntrySet() ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
|
|
+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.unmodifiable( sortedMap.keySet() ); return (LongSortedSet )keys; }
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
|
|
+ public long firstLongKey() { return sortedMap.firstLongKey(); }
|
|
+ public long lastLongKey() { return sortedMap.lastLongKey(); }
|
|
+ public Long firstKey() { return sortedMap.firstKey(); }
|
|
+ public Long lastKey() { return sortedMap.lastKey(); }
|
|
+ public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) { return new UnmodifiableSortedMap <V>( sortedMap.subMap( from, to ) ); }
|
|
+ public Long2ObjectSortedMap <V> headMap( final Long to ) { return new UnmodifiableSortedMap <V>( sortedMap.headMap( to ) ); }
|
|
+ public Long2ObjectSortedMap <V> tailMap( final Long from ) { return new UnmodifiableSortedMap <V>( sortedMap.tailMap( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted map backed by the given type-specific sorted map.
|
|
+ *
|
|
+ * @param m the sorted map to be wrapped in an unmodifiable sorted map.
|
|
+ * @return an unmodifiable view of the specified sorted map.
|
|
+ * @see java.util.Collections#unmodifiableSortedMap(SortedMap)
|
|
+ */
|
|
+ public static <V> Long2ObjectSortedMap <V> unmodifiable( final Long2ObjectSortedMap <V> m ) { return new UnmodifiableSortedMap <V>( m ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
|
|
new file mode 100644
|
|
index 0000000..6242492
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
|
|
@@ -0,0 +1,226 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.io.Serializable;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based FIFO queue, supporting also deque operations.
|
|
+ *
|
|
+ * <P>Instances of this class represent a FIFO queue using a backing
|
|
+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
|
|
+ * to reduce its memory usage, if necessary.
|
|
+ *
|
|
+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
|
|
+ */
|
|
+public class LongArrayFIFOQueue extends AbstractLongPriorityQueue implements Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ /** The standard initial capacity of a queue. */
|
|
+ public final static int INITIAL_CAPACITY = 4;
|
|
+ /** The backing array. */
|
|
+ protected transient long array[];
|
|
+ /** The current (cached) length of {@link #array}. */
|
|
+ protected transient int length;
|
|
+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
|
|
+ protected transient int start;
|
|
+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
|
|
+ * Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
|
|
+ protected transient int end;
|
|
+ /** Creates a new empty queue with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+
|
|
+ public LongArrayFIFOQueue( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ array = new long[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
|
|
+ length = array.length;
|
|
+ }
|
|
+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
|
|
+ */
|
|
+ public LongArrayFIFOQueue() {
|
|
+ this( INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Returns <code>null</code> (FIFO queues have no comparator).
|
|
+ * @return <code>null</code>.
|
|
+ */
|
|
+ @Override
|
|
+ public LongComparator comparator() {
|
|
+ return null;
|
|
+ }
|
|
+ @Override
|
|
+ public long dequeueLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ final long t = array[ start ];
|
|
+ if ( ++start == length ) start = 0;
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+ /** Dequeues the last element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ public long dequeueLastLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ if ( end == 0 ) end = length;
|
|
+ final long t = array[ --end ];
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+
|
|
+ private final void resize( final int size, final int newLength ) {
|
|
+ final long[] newArray = new long[ newLength ];
|
|
+ if ( start >= end ) {
|
|
+ if ( size != 0 ) {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ }
|
|
+ else System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ start = 0;
|
|
+ end = size;
|
|
+ array = newArray;
|
|
+ length = newLength;
|
|
+ }
|
|
+ private final void expand() {
|
|
+ resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
|
|
+ }
|
|
+ private final void reduce() {
|
|
+ final int size = size();
|
|
+ if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
|
|
+ }
|
|
+ @Override
|
|
+ public void enqueue( long x ) {
|
|
+ array[ end++ ] = x;
|
|
+ if ( end == length ) end = 0;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
|
|
+ */
|
|
+ public void enqueueFirst( long x ) {
|
|
+ if ( start == 0 ) start = length;
|
|
+ array[ --start ] = x;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Returns the first element of the queue.
|
|
+ * @return the first element of the queue.
|
|
+ */
|
|
+ public long firstLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ start ];
|
|
+ }
|
|
+ /** Returns the last element of the queue.
|
|
+ * @return the last element of the queue.
|
|
+ */
|
|
+ public long lastLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ ( end == 0 ? length : end ) - 1 ];
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ start = end = 0;
|
|
+ }
|
|
+ /** Trims the queue to the smallest possible size. */
|
|
+
|
|
+ public void trim() {
|
|
+ final int size = size();
|
|
+ final long[] newArray =
|
|
+ new long[ size + 1 ];
|
|
+ if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ else {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ start = 0;
|
|
+ length = ( end = size ) + 1;
|
|
+ array = newArray;
|
|
+ }
|
|
+ @Override
|
|
+ public int size() {
|
|
+ final int apparentLength = end - start;
|
|
+ return apparentLength >= 0 ? apparentLength : length + apparentLength;
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ int size = size();
|
|
+ s.writeInt( size );
|
|
+ for( int i = start; size-- != 0; ) {
|
|
+ s.writeLong( array[ i++ ] );
|
|
+ if ( i == length ) i = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ end = s.readInt();
|
|
+ array = new long[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
|
|
+ for( int i = 0; i < end; i++ ) array[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
|
|
new file mode 100644
|
|
index 0000000..11d1194
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
|
|
@@ -0,0 +1,501 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling its current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible. The backing array is exposed by the
|
|
+ * {@link #elements()} method.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class LongArrayList extends AbstractLongList implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353130L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** The backing array. */
|
|
+ protected transient long a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected LongArrayList( final long a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+
|
|
+ public LongArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = new long[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public LongArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final Collection<? extends Long> c ) {
|
|
+ this( c.size() );
|
|
+ size = LongIterators.unwrap( LongIterators.asLongIterator( c.iterator() ), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongCollection c ) {
|
|
+ this( c.size() );
|
|
+ size = LongIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongList l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final long a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public LongArrayList( final long a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final Iterator<? extends Long> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongIterator i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.nextLong() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public long[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static LongArrayList wrap( final long a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final LongArrayList l = new LongArrayList ( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static LongArrayList wrap( final long a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ a = LongArrays.ensureCapacity( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ private void grow( final int capacity ) {
|
|
+ a = LongArrays.grow( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public long getLong( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final long k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final long k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public long removeLong( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final long old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeLong( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public long set( final int index, final long k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ long old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final long t[] = new long[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final long[] a, final int offset, final int length ) {
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final long a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ public long[] toLongArray( long a[] ) {
|
|
+ if ( a == null || a.length < size ) a = new long[ size ];
|
|
+ System.arraycopy( this.a, 0, a, 0, size );
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( int index, final LongCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ final LongIterator i = c.iterator();
|
|
+ size += n;
|
|
+ while( n-- != 0 ) a[ index++ ] = i.nextLong();
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ ensureIndex( index );
|
|
+ final int n = l.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ l.getElements( 0, a, index, n );
|
|
+ size += n;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final LongCollection c ) {
|
|
+ final long[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final long[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( (Long.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ LongArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongArrayList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public LongArrayList clone() {
|
|
+ LongArrayList c = new LongArrayList ( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final LongArrayList l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final long[] a1 = a;
|
|
+ final long[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final LongArrayList l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final long a1[] = a, a2[] = l.a;
|
|
+ long e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new long[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..8b3f90d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
|
|
@@ -0,0 +1,229 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a backing
|
|
+ * array—all operations are performed directly on the array. The array is
|
|
+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
|
|
+ * to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small.
|
|
+ */
|
|
+public class LongArrayPriorityQueue extends AbstractLongPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array. */
|
|
+
|
|
+ protected transient long array[] = LongArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected LongComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ transient protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ transient protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public LongArrayPriorityQueue( int capacity, LongComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new long[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( LongComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, int size, final LongComparator c ) {
|
|
+ this( c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, final LongComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Returns the index of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ long first = array[ firstIndex ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ private void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+
|
|
+ public void enqueue( long x ) {
|
|
+ if ( size == array.length ) array = LongArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public long dequeueLong() {
|
|
+ ensureNonEmpty();
|
|
+ final int first = findFirst();
|
|
+ final long result = array[ first ];
|
|
+ System.arraycopy( array, first + 1, array, first, --size - first );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public long firstLong() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = LongArrays.trim( array, size );
|
|
+ }
|
|
+ public LongComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( array.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( array[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ array = new long[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) array[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
|
|
new file mode 100644
|
|
index 0000000..d9e82a2
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
|
|
@@ -0,0 +1,218 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class LongArraySet extends AbstractLongSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient long[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public LongArraySet( final long[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public LongArraySet() {
|
|
+ this.a = LongArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public LongArraySet( final int capacity ) {
|
|
+ this.a = new long[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public LongArraySet( LongCollection c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public LongArraySet( final Collection<? extends Long> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public LongArraySet( final long[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final long o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ public LongIterator iterator() {
|
|
+ return new AbstractLongIterator () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final long k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final long k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final long[] b = new long[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongArraySet clone() {
|
|
+ LongArraySet c;
|
|
+ try {
|
|
+ c = (LongArraySet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new long[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
|
|
new file mode 100644
|
|
index 0000000..0f453ac
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
|
|
@@ -0,0 +1,2463 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.concurrent.Callable;
|
|
+import java.util.concurrent.ExecutorCompletionService;
|
|
+import java.util.concurrent.ExecutorService;
|
|
+import java.util.concurrent.Executors;
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
|
|
+ * contain several methods make it possible to load and save arrays of primitive types as sequences
|
|
+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
|
|
+ * to sort an array using the values in another array as comparator.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
|
|
+ * on random-looking data. In
|
|
+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
|
|
+ * exploits parallelism better.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class LongArrays {
|
|
+ private LongArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static long[] EMPTY_ARRAY = {};
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static long[] ensureCapacity( final long[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final long t[] =
|
|
+ new long[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static long[] ensureCapacity( final long[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final long t[] =
|
|
+ new long[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>array.length</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static long[] grow( final long[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final long t[] =
|
|
+ new long[ newLength ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length, preserving just a part of the array.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>preserve</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static long[] grow( final long[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final long t[] =
|
|
+ new long[ newLength ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Trims the given array to the given length.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new maximum length for the array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code>
|
|
+ * entries or less; otherwise, an array with
|
|
+ * <code>length</code> entries whose entries are the same as
|
|
+ * the first <code>length</code> entries of <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static long[] trim( final long[] array, final int length ) {
|
|
+ if ( length >= array.length ) return array;
|
|
+ final long t[] =
|
|
+ length == 0 ? EMPTY_ARRAY : new long[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, length );
|
|
+ return t;
|
|
+ }
|
|
+ /** Sets the length of the given array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new length for the array.
|
|
+ * @return <code>array</code>, if it contains exactly <code>length</code>
|
|
+ * entries; otherwise, if it contains <em>more</em> than
|
|
+ * <code>length</code> entries, an array with <code>length</code> entries
|
|
+ * whose entries are the same as the first <code>length</code> entries of
|
|
+ * <code>array</code>; otherwise, an array with <code>length</code> entries
|
|
+ * whose first <code>array.length</code> entries are the same as those of
|
|
+ * <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static long[] setLength( final long[] array, final int length ) {
|
|
+ if ( length == array.length ) return array;
|
|
+ if ( length < array.length ) return trim( array, length );
|
|
+ return ensureCapacity( array, length );
|
|
+ }
|
|
+ /** Returns a copy of a portion of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param offset the first element to copy.
|
|
+ * @param length the number of elements to copy.
|
|
+ * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static long[] copy( final long[] array, final int offset, final int length ) {
|
|
+ ensureOffsetLength( array, offset, length );
|
|
+ final long[] a =
|
|
+ length == 0 ? EMPTY_ARRAY : new long[ length ];
|
|
+ System.arraycopy( array, offset, a, 0, length );
|
|
+ return a;
|
|
+ }
|
|
+ /** Returns a copy of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @return a copy of <code>array</code>.
|
|
+ */
|
|
+ public static long[] copy( final long[] array ) {
|
|
+ return array.clone();
|
|
+ }
|
|
+ /** Fills the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param value the new value for all elements of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static void fill( final long[] array, final long value ) {
|
|
+ int i = array.length;
|
|
+ while( i-- != 0 ) array[ i ] = value;
|
|
+ }
|
|
+ /** Fills a portion of the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param from the starting index of the portion to fill (inclusive).
|
|
+ * @param to the end index of the portion to fill (exclusive).
|
|
+ * @param value the new value for all elements of the specified portion of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static void fill( final long[] array, final int from, int to, final long value ) {
|
|
+ ensureFromTo( array, from, to );
|
|
+ if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
|
|
+ else for( int i = from; i < to; i++ ) array[ i ] = value;
|
|
+ }
|
|
+ /** Returns true if the two arrays are elementwise equal.
|
|
+ *
|
|
+ * @param a1 an array.
|
|
+ * @param a2 another array.
|
|
+ * @return true if the two arrays are of the same length, and their elements are equal.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static boolean equals( final long[] a1, final long a2[] ) {
|
|
+ int i = a1.length;
|
|
+ if ( i != a2.length ) return false;
|
|
+ while( i-- != 0 ) if (! ( (a1[ i ]) == (a2[ i ]) ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param from a start index (inclusive).
|
|
+ * @param to an end index (exclusive).
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
|
|
+ */
|
|
+ public static void ensureFromTo( final long[] a, final int from, final int to ) {
|
|
+ Arrays.ensureFromTo( a.length, from, to );
|
|
+ }
|
|
+ /** Ensures that a range given by an offset and a length fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param offset a start index.
|
|
+ * @param length a length (the number of elements in the range).
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
|
|
+ */
|
|
+ public static void ensureOffsetLength( final long[] a, final int offset, final int length ) {
|
|
+ Arrays.ensureOffsetLength( a.length, offset, length );
|
|
+ }
|
|
+ /** Ensures that two arrays are of the same length.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param b another array.
|
|
+ * @throws IllegalArgumentException if the two argument arrays are not of the same length.
|
|
+ */
|
|
+ public static void ensureSameLength( final long[] a, final long[] b ) {
|
|
+ if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
|
|
+ }
|
|
+ private static final int QUICKSORT_NO_REC = 16;
|
|
+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
|
|
+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
|
|
+ private static final int MERGESORT_NO_REC = 16;
|
|
+ /** Swaps two elements of an anrray.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ */
|
|
+ public static void swap( final long x[], final int a, final int b ) {
|
|
+ final long t = x[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ x[ b ] = t;
|
|
+ }
|
|
+ /** Swaps two sequences of elements of an array.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ * @param n the number of elements to exchange starting at {@code a} and {@code b}.
|
|
+ */
|
|
+ public static void swap( final long[] x, int a, int b, final int n ) {
|
|
+ for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
|
|
+ }
|
|
+ private static int med3( final long x[], final int a, final int b, final int c, LongComparator comp ) {
|
|
+ final int ab = comp.compare( x[ a ], x[ b ] );
|
|
+ final int ac = comp.compare( x[ a ], x[ c ] );
|
|
+ final int bc = comp.compare( x[ b ], x[ c ] );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static void selectionSort( final long[] a, final int from, final int to, final LongComparator comp ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final long u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ private static void insertionSort( final long[] a, final int from, final int to, final LongComparator comp ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ long t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( long u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final long[] x, final int from, final int to, final LongComparator comp ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s, comp );
|
|
+ m = med3( x, m - s, m, m + s, comp );
|
|
+ n = med3( x, n - 2 * s, n - s, n, comp );
|
|
+ }
|
|
+ m = med3( x, l, m, n, comp ); // Mid-size, med of 3
|
|
+ final long v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final long[] x, final LongComparator comp ) {
|
|
+ quickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortComp extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final long[] x;
|
|
+ private final LongComparator comp;
|
|
+ public ForkJoinQuickSortComp( final long[] x , final int from , final int to, final LongComparator comp ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.comp = comp;
|
|
+ }
|
|
+ @Override
|
|
+ protected void compute() {
|
|
+ final long[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final long v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ), new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp ( x, from, from + s, comp ) );
|
|
+ else invokeAll( new ForkJoinQuickSortComp ( x, to - t, to, comp ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x, final int from, final int to, final LongComparator comp ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortComp ( x, from, to, comp ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x, final LongComparator comp ) {
|
|
+ parallelQuickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+
|
|
+ private static int med3( final long x[], final int a, final int b, final int c ) {
|
|
+ final int ab = ( Long.compare((x[ a ]),(x[ b ])) );
|
|
+ final int ac = ( Long.compare((x[ a ]),(x[ c ])) );
|
|
+ final int bc = ( Long.compare((x[ b ]),(x[ c ])) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static void selectionSort( final long[] a, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( ( (a[ j ]) < (a[ m ]) ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final long u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private static void insertionSort( final long[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ long t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( long u = a[ j - 1 ]; ( (t) < (u) ); u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSort( final long[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, l, m, n ); // Mid-size, med of 3
|
|
+ final long v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Long.compare((x[ b ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( Long.compare((x[ c ]),(v)) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void quickSort( final long[] x ) {
|
|
+ quickSort( x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final long[] x;
|
|
+ public ForkJoinQuickSort( final long[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final long[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final long v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Long.compare((x[ b ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( Long.compare((x[ c ]),(v)) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ), new ForkJoinQuickSort ( x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort ( x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort ( x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort ( x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x ) {
|
|
+ parallelQuickSort( x, 0, x.length );
|
|
+ }
|
|
+
|
|
+ private static int med3Indirect( final int perm[], final long x[], final int a, final int b, final int c ) {
|
|
+ final long aa = x[ perm[ a ] ];
|
|
+ final long bb = x[ perm[ b ] ];
|
|
+ final long cc = x[ perm[ c ] ];
|
|
+ final int ab = ( Long.compare((aa),(bb)) );
|
|
+ final int ac = ( Long.compare((aa),(cc)) );
|
|
+ final int bc = ( Long.compare((bb),(cc)) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static void insertionSortIndirect( final int[] perm, final long[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = perm[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ); u = perm[ --j - 1 ] ) {
|
|
+ perm[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ perm[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSortIndirect( final int[] perm, final long[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
|
|
+ final long v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Long.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( Long.compare((x[ perm[ c ] ]),(v)) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ */
|
|
+ public static void quickSortIndirect( final int perm[], final long[] x ) {
|
|
+ quickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortIndirect extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] perm;
|
|
+ private final long[] x;
|
|
+ public ForkJoinQuickSortIndirect( final int perm[], final long[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.perm = perm;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final long[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ m = med3Indirect( perm, x, l, m, n );
|
|
+ final long v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( Long.compare((x[ perm[ b ] ]),(v)) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( Long.compare((x[ perm[ c ] ]),(v)) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ), new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect ( perm, x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSortIndirect ( perm, x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSortIndirect( final int[] perm, final long[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortIndirect ( perm, x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static void parallelQuickSortIndirect( final int perm[], final long[] x ) {
|
|
+ parallelQuickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ * @param from the index of the first element (inclusive) to be stabilized.
|
|
+ * @param to the index of the last element (exclusive) to be stabilized.
|
|
+ */
|
|
+ public static void stabilize( final int perm[], final long[] x, final int from, final int to ) {
|
|
+ int curr = from;
|
|
+ for( int i = from + 1; i < to; i++ ) {
|
|
+ if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
|
|
+ if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
|
|
+ curr = i;
|
|
+ }
|
|
+ }
|
|
+ if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ */
|
|
+ public static void stabilize( final int perm[], final long[] x ) {
|
|
+ stabilize( perm, x, 0, perm.length );
|
|
+ }
|
|
+
|
|
+ private static int med3( final long x[], final long[] y, final int a, final int b, final int c ) {
|
|
+ int t;
|
|
+ final int ab = ( t = ( Long.compare((x[ a ]),(x[ b ])) ) ) == 0 ? ( Long.compare((y[ a ]),(y[ b ])) ) : t;
|
|
+ final int ac = ( t = ( Long.compare((x[ a ]),(x[ c ])) ) ) == 0 ? ( Long.compare((y[ a ]),(y[ c ])) ) : t;
|
|
+ final int bc = ( t = ( Long.compare((x[ b ]),(x[ c ])) ) ) == 0 ? ( Long.compare((y[ b ]),(y[ c ])) ) : t;
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static void swap( final long x[], final long[] y, final int a, final int b ) {
|
|
+ final long t = x[ a ];
|
|
+ final long u = y[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ y[ a ] = y[ b ];
|
|
+ x[ b ] = t;
|
|
+ y[ b ] = u;
|
|
+ }
|
|
+ private static void swap( final long[] x, final long[] y, int a, int b, final int n ) {
|
|
+ for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
|
|
+ }
|
|
+
|
|
+ private static void selectionSort( final long[] a, final long[] b, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i, u;
|
|
+ for( int j = i + 1; j < to; j++ )
|
|
+ if ( ( u = ( Long.compare((a[ j ]),(a[ m ])) ) ) < 0 || u == 0 && ( (b[ j ]) < (b[ m ]) ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ long t = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = t;
|
|
+ t = b[ i ];
|
|
+ b[ i ] = b[ m ];
|
|
+ b[ m ] = t;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+
|
|
+ public static void quickSort( final long[] x, final long[] y, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, y, l, m, n ); // Mid-size, med of 3
|
|
+ final long v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( Long.compare((x[ b ]),(v)) ) ) == 0 ? ( Long.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( Long.compare((x[ c ]),(v)) ) ) == 0 ? ( Long.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static void quickSort( final long[] x, final long[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ quickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort2 extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final long[] x, y;
|
|
+ public ForkJoinQuickSort2( final long[] x, final long[] y, final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.y = y;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ protected void compute() {
|
|
+ final long[] x = this.x;
|
|
+ final long[] y = this.y;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ m = med3( x, y, l, m, n );
|
|
+ final long v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( Long.compare((x[ b ]),(v)) ) ) == 0 ? ( Long.compare((y[ b ]),(w)) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( Long.compare((x[ c ]),(v)) ) ) == 0 ? ( Long.compare((y[ c ]),(w)) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ), new ForkJoinQuickSort2 ( x, y, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 ( x, y, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort2 ( x, y, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x, final long[] y, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort2 ( x, y, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static void parallelQuickSort( final long[] x, final long[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ parallelQuickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+
|
|
+ public static void mergeSort( final long a[], final int from, final int to, final long supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, a );
|
|
+ mergeSort( supp, mid, to, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( ( (supp[ mid - 1 ]) <= (supp[ mid ]) ) ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && ( (supp[ p ]) <= (supp[ q ]) ) ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void mergeSort( final long a[], final int from, final int to ) {
|
|
+ mergeSort( a, from, to, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void mergeSort( final long a[] ) {
|
|
+ mergeSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+ public static void mergeSort( final long a[], final int from, final int to, LongComparator comp, final long supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, comp, a );
|
|
+ mergeSort( supp, mid, to, comp, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void mergeSort( final long a[], final int from, final int to, LongComparator comp ) {
|
|
+ mergeSort( a, from, to, comp, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static void mergeSort( final long a[], LongComparator comp ) {
|
|
+ mergeSort( a, 0, a.length, comp );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+
|
|
+ public static int binarySearch( final long[] a, int from, int to, final long key ) {
|
|
+ long midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ if (midVal < key) from = mid + 1;
|
|
+ else if (midVal > key) to = mid - 1;
|
|
+ else return mid;
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final long[] a, final long key ) {
|
|
+ return binarySearch( a, 0, a.length, key );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final long[] a, int from, int to, final long key, final LongComparator c ) {
|
|
+ long midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ final int cmp = c.compare( midVal, key );
|
|
+ if ( cmp < 0 ) from = mid + 1;
|
|
+ else if (cmp > 0) to = mid - 1;
|
|
+ else return mid; // key found
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static int binarySearch( final long[] a, final long key, final LongComparator c ) {
|
|
+ return binarySearch( a, 0, a.length, key, c );
|
|
+ }
|
|
+ /** The size of a digit used during radix sort (must be a power of 2). */
|
|
+ private static final int DIGIT_BITS = 8;
|
|
+ /** The mask to extract a digit of {@link #DIGIT_BITS} bits. */
|
|
+ private static final int DIGIT_MASK = ( 1 << DIGIT_BITS ) - 1;
|
|
+ /** The number of digits per element. */
|
|
+ private static final int DIGITS_PER_ELEMENT = Long.SIZE / DIGIT_BITS;
|
|
+ private static final int RADIXSORT_NO_REC = 1024;
|
|
+ private static final int PARALLEL_RADIXSORT_NO_FORK = 1024;
|
|
+ /** This method fixes negative numbers so that the combination exponent/significand is lexicographically sorted. */
|
|
+ /** Sorts the specified array using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation is significantly faster than quicksort
|
|
+ * already at small sizes (say, more than 10000 elements), but it can only
|
|
+ * sort in ascending order.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final long[] a ) {
|
|
+ radixSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of an array using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation is significantly faster than quicksort
|
|
+ * already at small sizes (say, more than 10000 elements), but it can only
|
|
+ * sort in ascending order.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final long[] a, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ quickSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ long t = a[ i ];
|
|
+ c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while ( ( d = --pos[ c ] ) > i ) {
|
|
+ final long z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) quickSort( a, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ protected final static class Segment {
|
|
+ protected final int offset, length, level;
|
|
+ protected Segment( final int offset, final int length, final int level ) {
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ this.level = level;
|
|
+ }
|
|
+ @Override
|
|
+ public String toString() {
|
|
+ return "Segment [offset=" + offset + ", length=" + length + ", level=" + level + "]";
|
|
+ }
|
|
+ }
|
|
+ protected final static Segment POISON_PILL = new Segment( -1, -1, -1 );
|
|
+ /** Sorts the specified range of an array using parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final long[] a, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ quickSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for(;;) {
|
|
+ if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((a[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ long t = a[ i ];
|
|
+ c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) {
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final long z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ c = (int)((t) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, i, i + count[ c ] );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts the specified array using parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final long[] a ) {
|
|
+ parallelRadixSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified array using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final long[] a, final boolean stable ) {
|
|
+ radixSortIndirect( perm, a, 0, perm.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified array using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
|
|
+ * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final long[] a, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, 0, perm, first, length );
|
|
+ for( int i = 0, p = first; i <= lastUsed; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, p, p + count[ i ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = p;
|
|
+ lengthStack[ stackPos ] = count[ i ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of an array using parallel indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void parallelRadixSortIndirect( final int perm[], final long[] a, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ radixSortIndirect( perm, a, from, to, stable );
|
|
+ return;
|
|
+ }
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ for( int i = numberOfThreads; i-- != 0; ) executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for(;;) {
|
|
+ if ( queueSize.get() == 0 ) for( int i = numberOfThreads; i-- != 0; ) queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ (int)((a[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, first, perm, first, length );
|
|
+ for( int i = 0, p = first; i <= lastUsed; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, p, p + count[ i ], stable );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( p, count[ i ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = (int)((a[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) radixSortIndirect( perm, a, i, i + count[ c ], stable );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts the specified array using parallel indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void parallelRadixSortIndirect( final int perm[], final long[] a, final boolean stable ) {
|
|
+ parallelRadixSortIndirect( perm, a, 0, a.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using radix sort.
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final long[] a, final long[] b ) {
|
|
+ ensureSameLength( a, b );
|
|
+ radixSort( a, b, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final long[] a, final long[] b, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ selectionSort( a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ long t = a[ i ];
|
|
+ long u = b[ i ];
|
|
+ c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ long z = t;
|
|
+ t = a[ d ];
|
|
+ a[ d ] = z;
|
|
+ z = u;
|
|
+ u = b[ d ];
|
|
+ b[ d ] = z;
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ b[ i ] = u;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays using a parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final long[] a, final long[] b, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_RADIXSORT_NO_FORK ) {
|
|
+ quickSort( a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch." );
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final LinkedBlockingQueue<Segment> queue = new LinkedBlockingQueue<Segment>();
|
|
+ queue.add( new Segment( from, to - from, 0 ) );
|
|
+ final AtomicInteger queueSize = new AtomicInteger( 1 );
|
|
+ final int numberOfThreads = Runtime.getRuntime().availableProcessors();
|
|
+ final ExecutorService executorService = Executors.newFixedThreadPool( numberOfThreads, Executors.defaultThreadFactory() );
|
|
+ final ExecutorCompletionService<Void> executorCompletionService = new ExecutorCompletionService<Void>( executorService );
|
|
+ for ( int i = numberOfThreads; i-- != 0; )
|
|
+ executorCompletionService.submit( new Callable<Void>() {
|
|
+ public Void call() throws Exception {
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ for ( ;; ) {
|
|
+ if ( queueSize.get() == 0 ) for ( int i = numberOfThreads; i-- != 0; )
|
|
+ queue.add( POISON_PILL );
|
|
+ final Segment segment = queue.take();
|
|
+ if ( segment == POISON_PILL ) return null;
|
|
+ final int first = segment.offset;
|
|
+ final int length = segment.length;
|
|
+ final int level = segment.level;
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS;
|
|
+ // Count keys.
|
|
+ for ( int i = first + length; i-- != first; )
|
|
+ count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ for ( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ long t = a[ i ];
|
|
+ long u = b[ i ];
|
|
+ c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while ( ( d = --pos[ c ] ) > i ) {
|
|
+ c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ final long z = t;
|
|
+ final long w = u;
|
|
+ t = a[ d ];
|
|
+ u = b[ d ];
|
|
+ a[ d ] = z;
|
|
+ b[ d ] = w;
|
|
+ }
|
|
+ a[ i ] = t;
|
|
+ b[ i ] = u;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < PARALLEL_RADIXSORT_NO_FORK ) quickSort( a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ queueSize.incrementAndGet();
|
|
+ queue.add( new Segment( i, count[ c ], level + 1 ) );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ queueSize.decrementAndGet();
|
|
+ }
|
|
+ }
|
|
+ } );
|
|
+ Throwable problem = null;
|
|
+ for ( int i = numberOfThreads; i-- != 0; )
|
|
+ try {
|
|
+ executorCompletionService.take().get();
|
|
+ }
|
|
+ catch ( Exception e ) {
|
|
+ problem = e.getCause(); // We keep only the last one. They will be logged anyway.
|
|
+ }
|
|
+ executorService.shutdown();
|
|
+ if ( problem != null ) throw ( problem instanceof RuntimeException ) ? (RuntimeException)problem : new RuntimeException( problem );
|
|
+ }
|
|
+ /** Sorts two arrays using a parallel radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of elements
|
|
+ * in the same position in the two provided arrays will be considered a single key, and permuted
|
|
+ * accordingly. In the end, either <code>a[ i ] < a[ i + 1 ]</code> or <code>a[ i ] == a[ i + 1 ]</code> and <code>b[ i ] ≤ b[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a pool of {@link Runtime#availableProcessors()} threads.
|
|
+ *
|
|
+ * @param a the first array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ */
|
|
+ public static void parallelRadixSort( final long[] a, final long[] b ) {
|
|
+ ensureSameLength( a, b );
|
|
+ parallelRadixSort( a, b, 0, a.length );
|
|
+ }
|
|
+ private static void insertionSortIndirect( final int[] perm, final long[] a, final long[] b, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = perm[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = perm[ j - 1 ]; ( (a[ t ]) < (a[ u ]) ) || ( (a[ t ]) == (a[ u ]) ) && ( (b[ t ]) < (b[ u ]) ); u = perm[ --j - 1 ] ) {
|
|
+ perm[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ perm[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final long[] a, final long[] b, final boolean stable ) {
|
|
+ ensureSameLength( a, b );
|
|
+ radixSortIndirect( perm, a, b, 0, a.length, stable );
|
|
+ }
|
|
+ /** Sorts the specified pair of arrays lexicographically using indirect radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>a[ perm[ i ] ] ≤ a[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation will allocate, in the stable case, a further support array as large as <code>perm</code> (note that the stable
|
|
+ * version is slightly faster).
|
|
+ *
|
|
+ * @param perm a permutation array indexing <code>a</code>.
|
|
+ * @param a the array to be sorted.
|
|
+ * @param b the second array to be sorted.
|
|
+ * @param from the index of the first element of <code>perm</code> (inclusive) to be permuted.
|
|
+ * @param to the index of the last element of <code>perm</code> (exclusive) to be permuted.
|
|
+ * @param stable whether the sorting algorithm should be stable.
|
|
+ */
|
|
+ public static void radixSortIndirect( final int[] perm, final long[] a, final long[] b, final int from, final int to, final boolean stable ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, a, b, from, to );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = 2;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] support = stable ? new int[ perm.length ] : null;
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final long[] k = level < DIGITS_PER_ELEMENT ? a : b; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = stable ? 0 : first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ if ( stable ) {
|
|
+ for( int i = first + length; i-- != first; ) support[ --pos[ (int)((k[ perm[ i ] ]) >>> shift & DIGIT_MASK ^ signMask) ] ] = perm[ i ];
|
|
+ System.arraycopy( support, 0, perm, first, length );
|
|
+ for( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( level < maxLevel && count[ i ] > 1 ) {
|
|
+ if ( count[ i ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, p, p + count[ i ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = p;
|
|
+ lengthStack[ stackPos ] = count[ i ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ p += count[ i ];
|
|
+ }
|
|
+ java.util.Arrays.fill( count, 0 );
|
|
+ }
|
|
+ else {
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ int t = perm[ i ];
|
|
+ c = (int)((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ final int z = t;
|
|
+ t = perm[ d ];
|
|
+ perm[ d ] = z;
|
|
+ c = (int)((k[ t ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ }
|
|
+ perm[ i ] = t;
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) insertionSortIndirect( perm, a, b, i, i + count[ c ] );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ private static void selectionSort( final long[][] a, final int from, final int to, final int level ) {
|
|
+ final int layers = a.length;
|
|
+ final int firstLayer = level / DIGITS_PER_ELEMENT;
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) {
|
|
+ for( int p = firstLayer; p < layers; p++ ) {
|
|
+ if ( a[ p ][ j ] < a[ p ][ m ] ) {
|
|
+ m = j;
|
|
+ break;
|
|
+ }
|
|
+ else if ( a[ p ][ j ] > a[ p ][ m ] ) break;
|
|
+ }
|
|
+ }
|
|
+ if ( m != i ) {
|
|
+ for( int p = layers; p-- != 0; ) {
|
|
+ final long u = a[ p ][ i ];
|
|
+ a[ p ][ i ] = a[ p ][ m ];
|
|
+ a[ p ][ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified array of arrays lexicographically using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
|
|
+ * in the same position will be considered a single key, and permuted
|
|
+ * accordingly.
|
|
+ *
|
|
+ * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
|
|
+ */
|
|
+ public static void radixSort( final long[][] a ) {
|
|
+ radixSort( a, 0, a[ 0 ].length );
|
|
+ }
|
|
+ /** Sorts the specified array of arrays lexicographically using radix sort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned radix sort adapted from Peter M. McIlroy, Keith Bostic and M. Douglas
|
|
+ * McIlroy, “Engineering radix sort”, <i>Computing Systems</i>, 6(1), pages 5−27 (1993).
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the provided arrays. Tuples of elements
|
|
+ * in the same position will be considered a single key, and permuted
|
|
+ * accordingly.
|
|
+ *
|
|
+ * @param a an array containing arrays of equal length to be sorted lexicographically in parallel.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static void radixSort( final long[][] a, final int from, final int to ) {
|
|
+ if ( to - from < RADIXSORT_NO_REC ) {
|
|
+ selectionSort( a, from, to, 0 );
|
|
+ return;
|
|
+ }
|
|
+ final int layers = a.length;
|
|
+ final int maxLevel = DIGITS_PER_ELEMENT * layers - 1;
|
|
+ for( int p = layers, l = a[ 0 ].length; p-- != 0; ) if ( a[ p ].length != l ) throw new IllegalArgumentException( "The array of index " + p + " has not the same length of the array of index 0." );
|
|
+ final int stackSize = ( ( 1 << DIGIT_BITS ) - 1 ) * ( layers * DIGITS_PER_ELEMENT - 1 ) + 1;
|
|
+ int stackPos = 0;
|
|
+ final int[] offsetStack = new int[ stackSize ];
|
|
+ final int[] lengthStack = new int[ stackSize ];
|
|
+ final int[] levelStack = new int[ stackSize ];
|
|
+ offsetStack[ stackPos ] = from;
|
|
+ lengthStack[ stackPos ] = to - from;
|
|
+ levelStack[ stackPos++ ] = 0;
|
|
+ final int[] count = new int[ 1 << DIGIT_BITS ];
|
|
+ final int[] pos = new int[ 1 << DIGIT_BITS ];
|
|
+ final long[] t = new long[ layers ];
|
|
+ while( stackPos > 0 ) {
|
|
+ final int first = offsetStack[ --stackPos ];
|
|
+ final int length = lengthStack[ stackPos ];
|
|
+ final int level = levelStack[ stackPos ];
|
|
+ final int signMask = level % DIGITS_PER_ELEMENT == 0 ? 1 << DIGIT_BITS - 1 : 0;
|
|
+ final long[] k = a[ level / DIGITS_PER_ELEMENT ]; // This is the key array
|
|
+ final int shift = ( DIGITS_PER_ELEMENT - 1 - level % DIGITS_PER_ELEMENT ) * DIGIT_BITS; // This is the shift that extract the right byte from a key
|
|
+ // Count keys.
|
|
+ for( int i = first + length; i-- != first; ) count[ (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask) ]++;
|
|
+ // Compute cumulative distribution
|
|
+ int lastUsed = -1;
|
|
+ for ( int i = 0, p = first; i < 1 << DIGIT_BITS; i++ ) {
|
|
+ if ( count[ i ] != 0 ) lastUsed = i;
|
|
+ pos[ i ] = ( p += count[ i ] );
|
|
+ }
|
|
+ final int end = first + length - count[ lastUsed ];
|
|
+ // i moves through the start of each block
|
|
+ for( int i = first, c = -1, d; i <= end; i += count[ c ], count[ c ] = 0 ) {
|
|
+ for( int p = layers; p-- != 0; ) t[ p ] = a[ p ][ i ];
|
|
+ c = (int)((k[ i ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ if ( i < end ) { // When all slots are OK, the last slot is necessarily OK.
|
|
+ while( ( d = --pos[ c ] ) > i ) {
|
|
+ c = (int)((k[ d ]) >>> shift & DIGIT_MASK ^ signMask);
|
|
+ for( int p = layers; p-- != 0; ) {
|
|
+ final long u = t[ p ];
|
|
+ t[ p ] = a[ p ][ d ];
|
|
+ a[ p ][ d ] = u;
|
|
+ }
|
|
+ }
|
|
+ for( int p = layers; p-- != 0; ) a[ p ][ i ] = t[ p ];
|
|
+ }
|
|
+ if ( level < maxLevel && count[ c ] > 1 ) {
|
|
+ if ( count[ c ] < RADIXSORT_NO_REC ) selectionSort( a, i, i + count[ c ], level + 1 );
|
|
+ else {
|
|
+ offsetStack[ stackPos ] = i;
|
|
+ lengthStack[ stackPos ] = count[ c ];
|
|
+ levelStack[ stackPos++ ] = level + 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param from the index of the first element (inclusive) to be shuffled.
|
|
+ * @param to the index of the last element (exclusive) to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static long[] shuffle( final long[] a, final int from, final int to, final Random random ) {
|
|
+ for( int i = to - from; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final long t = a[ from + i ];
|
|
+ a[ from + i ] = a[ from + p ];
|
|
+ a[ from + p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Shuffles the specified array using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static long[] shuffle( final long[] a, final Random random ) {
|
|
+ for( int i = a.length; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final long t = a[ i ];
|
|
+ a[ i ] = a[ p ];
|
|
+ a[ p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static long[] reverse( final long[] a ) {
|
|
+ final int length = a.length;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final long t = a[ length - i - 1 ];
|
|
+ a[ length - i - 1 ] = a[ i ];
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array fragment.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @param from the index of the first element (inclusive) to be reversed.
|
|
+ * @param to the index of the last element (exclusive) to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static long[] reverse( final long[] a, final int from, final int to ) {
|
|
+ final int length = to - from;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final long t = a[ from + length - i - 1 ];
|
|
+ a[ from + length - i - 1 ] = a[ from + i ];
|
|
+ a[ from + i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays. */
|
|
+ private static final class ArrayHashStrategy implements Hash.Strategy<long[]>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ public int hashCode( final long[] o ) {
|
|
+ return java.util.Arrays.hashCode( o );
|
|
+ }
|
|
+ public boolean equals( final long[] a, final long[] b ) {
|
|
+ return java.util.Arrays.equals( a, b );
|
|
+ }
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays.
|
|
+ *
|
|
+ * <P>This hash strategy may be used in custom hash collections whenever keys are
|
|
+ * arrays, and they must be considered equal by content. This strategy
|
|
+ * will handle <code>null</code> correctly, and it is serializable.
|
|
+ */
|
|
+ public final static Hash.Strategy<long[]> HASH_STRATEGY = new ArrayHashStrategy();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..ae2906f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
|
|
@@ -0,0 +1,97 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface LongBidirectionalIterator extends LongIterator , ObjectBidirectionalIterator<Long> {
|
|
+ /**
|
|
+ * Returns the previous element as a primitive type.
|
|
+ *
|
|
+ * @return the previous element in the iteration.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+ long previousLong();
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
|
|
new file mode 100644
|
|
index 0000000..0708d1f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
|
|
@@ -0,0 +1,169 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface LongCollection extends Collection<Long>, LongIterable {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ LongIterator iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongIterator longIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+ /**
|
|
+ * @see Collection#contains(Object)
|
|
+ */
|
|
+ boolean contains( long key );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray()
|
|
+ */
|
|
+ long[] toLongArray();
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ long[] toLongArray( long a[] );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ long[] toArray( long a[] );
|
|
+ /**
|
|
+ * @see Collection#add(Object)
|
|
+ */
|
|
+ boolean add( long key );
|
|
+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface
|
|
+ * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
|
|
+ * <code>remove()</code>.
|
|
+ *
|
|
+ * @see Collection#remove(Object)
|
|
+ */
|
|
+ boolean rem( long key );
|
|
+ /**
|
|
+ * @see Collection#addAll(Collection)
|
|
+ */
|
|
+ boolean addAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#containsAll(Collection)
|
|
+ */
|
|
+ boolean containsAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#removeAll(Collection)
|
|
+ */
|
|
+ boolean removeAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#retainAll(Collection)
|
|
+ */
|
|
+ boolean retainAll( LongCollection c );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
|
|
new file mode 100644
|
|
index 0000000..1574de8
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
|
|
@@ -0,0 +1,237 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongCollections {
|
|
+ private LongCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection extends AbstractLongCollection {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( long k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public long[] toLongArray( long[] a ) { return a; }
|
|
+ public long[] toLongArray() { return LongArrays.EMPTY_ARRAY; }
|
|
+ public boolean rem( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( LongCollection c ) { return c.isEmpty(); }
|
|
+
|
|
+ public LongBidirectionalIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection implements LongCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongCollection collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final LongCollection c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final LongCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final long o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public long[] toLongArray() { synchronized( sync ) { return collection.toLongArray(); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public long[] toLongArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
|
|
+ public long[] toArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
|
|
+ public boolean addAll( final LongCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final LongCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final LongCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final LongCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public boolean add( final Long k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public LongIterator iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ public boolean add( final long k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final long k ) { synchronized( sync ) { return collection.rem( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection synchronize( final LongCollection c ) { return new SynchronizedCollection ( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection synchronize( final LongCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection implements LongCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongCollection collection;
|
|
+ protected UnmodifiableCollection( final LongCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final long o ) { return collection.contains( o ); }
|
|
+ public LongIterator iterator() { return LongIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ public long[] toLongArray() { return collection.toLongArray(); }
|
|
+ public long[] toLongArray( final long[] a ) { return collection.toLongArray( a ); }
|
|
+ public long[] toArray( final long[] a ) { return collection.toArray( a ); }
|
|
+ public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final LongCollection c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return collection.contains( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection unmodifiable( final LongCollection c ) { return new UnmodifiableCollection ( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection extends AbstractLongCollection implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongIterable iterable;
|
|
+ protected IterableCollection( final LongIterable iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final LongIterator iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public LongIterator iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static LongCollection asCollection( final LongIterable iterable ) {
|
|
+ if ( iterable instanceof LongCollection ) return (LongCollection )iterable;
|
|
+ return new IterableCollection ( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
|
|
new file mode 100644
|
|
index 0000000..31e394a
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
|
|
@@ -0,0 +1,90 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Comparator;
|
|
+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
|
|
+ * and as primitive types.
|
|
+ *
|
|
+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
|
|
+ * can be used to implement this interface just by specifying the type-specific
|
|
+ * comparator.
|
|
+ *
|
|
+ * @see Comparator
|
|
+ */
|
|
+public interface LongComparator extends Comparator<Long> {
|
|
+ /** Compares the given primitive types.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ * @return A positive integer, zero, or a negative integer if the first
|
|
+ * argument is greater than, equal to, or smaller than, respectively, the
|
|
+ * second one.
|
|
+ */
|
|
+ public int compare( long k1, long k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
|
|
new file mode 100644
|
|
index 0000000..7098bbc
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
|
|
@@ -0,0 +1,113 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with comparators.
|
|
+ */
|
|
+public class LongComparators {
|
|
+ private LongComparators() {}
|
|
+ /** A type-specific comparator mimicking the natural order. */
|
|
+ protected static class NaturalImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return ( Long.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return NATURAL_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final LongComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
|
|
+ /** A type-specific comparator mimicking the opposite of the natural order. */
|
|
+ protected static class OppositeImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return - ( Long.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return OPPOSITE_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final LongComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
|
|
+ protected static class OppositeComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final LongComparator comparator;
|
|
+ protected OppositeComparator( final LongComparator c ) {
|
|
+ comparator = c;
|
|
+ }
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return comparator.compare( b, a );
|
|
+ }
|
|
+ };
|
|
+ /** Returns a comparator representing the opposite order of the given comparator.
|
|
+ *
|
|
+ * @param c a comparator.
|
|
+ * @return a comparator representing the opposite order of <code>c</code>.
|
|
+ */
|
|
+ public static LongComparator oppositeComparator( final LongComparator c ) {
|
|
+ return new OppositeComparator ( c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
|
|
new file mode 100644
|
|
index 0000000..5b394ab
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
|
|
@@ -0,0 +1,96 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+/** A type-specific {@link Hash} interface.
|
|
+ *
|
|
+ * @see Hash
|
|
+ */
|
|
+public interface LongHash {
|
|
+ /** A type-specific hash strategy.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Hash.Strategy
|
|
+ */
|
|
+ public interface Strategy {
|
|
+ /** Returns the hash code of the specified element with respect to this hash strategy.
|
|
+ *
|
|
+ * @param e an element.
|
|
+ * @return the hash code of the given element with respect to this hash strategy.
|
|
+ */
|
|
+ public int hashCode( long e );
|
|
+ /** Returns true if the given elements are equal with respect to this hash strategy.
|
|
+ *
|
|
+ * @param a an element.
|
|
+ * @param b another element.
|
|
+ * @return true if the two specified elements are equal with respect to this hash strategy.
|
|
+ */
|
|
+ public boolean equals( long a, long b );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
|
|
new file mode 100644
|
|
index 0000000..b63b1a2
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
|
|
@@ -0,0 +1,155 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with heaps.
|
|
+ *
|
|
+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
|
|
+ * are used in the implementation of heap-based queues, but they may be also used
|
|
+ * directly.
|
|
+ *
|
|
+ */
|
|
+public class LongHeaps {
|
|
+ private LongHeaps() {}
|
|
+ /** Moves the given element down into the heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final long[] heap, final int size, int i, final LongComparator c ) {
|
|
+ assert i < size;
|
|
+ final long e = heap[ i ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ long t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
|
|
+ if ( ( (e) <= (t) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ long t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( e, t ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final long[] heap, final int size, int i, final LongComparator c ) {
|
|
+ assert i < size;
|
|
+ final long e = heap[ i ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final long t = heap[ parent ];
|
|
+ if ( ( (t) <= (e) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final long t = heap[ parent ];
|
|
+ if ( c.compare( t, e ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Makes an array into a heap.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final long[] heap, final int size, final LongComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( heap, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
|
|
new file mode 100644
|
|
index 0000000..b9bdf8b
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
|
|
@@ -0,0 +1,88 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “colon” <code>for</code> statements with primitive-type
|
|
+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
|
|
+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
|
|
+ *
|
|
+ * @see Iterable
|
|
+ */
|
|
+public interface LongIterable extends Iterable<Long> {
|
|
+ /** Returns a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * @return a type-specific iterator.
|
|
+ */
|
|
+ LongIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
|
|
new file mode 100644
|
|
index 0000000..9838448
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
|
|
@@ -0,0 +1,96 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface LongIterator extends Iterator<Long> {
|
|
+ /**
|
|
+ * Returns the next element as a primitive type.
|
|
+ *
|
|
+ * @return the next element in the iteration.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ long nextLong();
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
|
|
new file mode 100644
|
|
index 0000000..1d71ab0
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
|
|
@@ -0,0 +1,658 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class LongIterators {
|
|
+ private LongIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator extends AbstractLongListIterator implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public long nextLong() { throw new NoSuchElementException(); }
|
|
+ public long previousLong() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator extends AbstractLongListIterator {
|
|
+ private final long element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static LongListIterator singleton( final long element ) {
|
|
+ return new SingletonIterator ( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator extends AbstractLongListIterator {
|
|
+ private final long[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final long[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static LongListIterator wrap( final long[] array, final int offset, final int length ) {
|
|
+ LongArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator ( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static LongListIterator wrap( final long[] array ) {
|
|
+ return new ArrayIterator ( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final long array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextLong();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final long array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+
|
|
+ public static long[] unwrap( final LongIterator i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ long array[] = new long[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = LongArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.nextLong();
|
|
+ }
|
|
+ return LongArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static long[] unwrap( final LongIterator i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final LongCollection c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.nextLong() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static long unwrap( final LongIterator i, final LongCollection c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.nextLong() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final LongIterator i, final LongCollection s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.nextLong() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final LongIterator i, final LongCollection s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static LongList pour( final LongIterator i, int max ) {
|
|
+ final LongArrayList l = new LongArrayList ();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static LongList pour( final LongIterator i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper extends AbstractLongIterator {
|
|
+ final Iterator<Long> i;
|
|
+ public IteratorWrapper( final Iterator<Long> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public long nextLong() { return ((i.next()).longValue()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static LongIterator asLongIterator( final Iterator i ) {
|
|
+ if ( i instanceof LongIterator ) return (LongIterator )i;
|
|
+ return new IteratorWrapper ( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper extends AbstractLongListIterator {
|
|
+ final ListIterator<Long> i;
|
|
+ public ListIteratorWrapper( final ListIterator<Long> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( long k ) { i.set( (Long.valueOf(k)) ); }
|
|
+ public void add( long k ) { i.add( (Long.valueOf(k)) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public long nextLong() { return ((i.next()).longValue()); }
|
|
+ public long previousLong() { return ((i.previous()).longValue()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static LongListIterator asLongIterator( final ListIterator i ) {
|
|
+ if ( i instanceof LongListIterator ) return (LongListIterator )i;
|
|
+ return new ListIteratorWrapper ( i );
|
|
+ }
|
|
+ private static class IntervalIterator extends AbstractLongBidirectionalIterator {
|
|
+ private final long from, to;
|
|
+ long curr;
|
|
+ public IntervalIterator( final long from, final long to ) {
|
|
+ this.from = this.curr = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < to; }
|
|
+ public boolean hasPrevious() { return curr > from; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return curr++;
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return --curr;
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( curr + n <= to ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = (int)( to - curr );
|
|
+ curr = to;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( curr - n >= from ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = (int)( curr - from );
|
|
+ curr = from;
|
|
+ return n;
|
|
+ }
|
|
+ }
|
|
+ /** Creates a type-specific bidirectional iterator over an interval.
|
|
+ *
|
|
+ * <P>The type-specific bidirectional iterator returned by this method will return the
|
|
+ * elements <code>from</code>, <code>from+1</code>,…, <code>to-1</code>.
|
|
+ *
|
|
+ * <P>Note that all other type-specific interval iterator are <em>list</em>
|
|
+ * iterators. Of course, this is not possible with longs as the index
|
|
+ * returned by {@link java.util.ListIterator#nextIndex() nextIndex()}/{@link
|
|
+ * java.util.ListIterator#previousIndex() previousIndex()} would exceed an integer.
|
|
+ *
|
|
+ * @param from the starting element (inclusive).
|
|
+ * @param to the ending element (exclusive).
|
|
+ * @return a type-specific bidirectional iterator enumerating the elements from <code>from</code> to <code>to</code>.
|
|
+ */
|
|
+ public static LongBidirectionalIterator fromTo( final long from, final long to ) {
|
|
+ return new IntervalIterator( from, to );
|
|
+ }
|
|
+ private static class IteratorConcatenator extends AbstractLongIterator {
|
|
+ final LongIterator a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final LongIterator a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ long next = a[ lastOffset = offset ].nextLong();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static LongIterator concat( final LongIterator a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static LongIterator concat( final LongIterator a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator ( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator extends AbstractLongIterator {
|
|
+ final protected LongIterator i;
|
|
+ public UnmodifiableIterator( final LongIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static LongIterator unmodifiable( final LongIterator i ) { return new UnmodifiableIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator extends AbstractLongBidirectionalIterator {
|
|
+ final protected LongBidirectionalIterator i;
|
|
+ public UnmodifiableBidirectionalIterator( final LongBidirectionalIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ public long previousLong() { return i.previousLong(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static LongBidirectionalIterator unmodifiable( final LongBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator extends AbstractLongListIterator {
|
|
+ final protected LongListIterator i;
|
|
+ public UnmodifiableListIterator( final LongListIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ public long previousLong() { return i.previousLong(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static LongListIterator unmodifiable( final LongListIterator i ) { return new UnmodifiableListIterator ( i ); }
|
|
+
|
|
+ /** A wrapper promoting the results of an IntIterator. */
|
|
+ protected static class IntIteratorWrapper implements LongIterator {
|
|
+ final it.unimi.dsi.fastutil.ints.IntIterator iterator;
|
|
+ public IntIteratorWrapper( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
|
|
+ this.iterator = iterator;
|
|
+ }
|
|
+ public boolean hasNext() { return iterator.hasNext(); }
|
|
+ public Long next() { return Long.valueOf( iterator.nextInt() ); }
|
|
+ public long nextLong() { return iterator.nextInt(); }
|
|
+ public void remove() { iterator.remove(); }
|
|
+ public int skip( final int n ) { return iterator.skip( n ); }
|
|
+ }
|
|
+ /** Returns an iterator backed by the specified integer iterator.
|
|
+ * @return an iterator backed by the specified integer iterator.
|
|
+ */
|
|
+ public static LongIterator wrap( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
|
|
+ return new IntIteratorWrapper( iterator );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
|
|
new file mode 100644
|
|
index 0000000..bc91a8f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
|
|
@@ -0,0 +1,210 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface LongList extends List<Long>, Comparable<List<? extends Long>>, LongCollection {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ LongListIterator iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongListIterator longListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongListIterator longListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ LongListIterator listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ LongListIterator listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongList longSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ LongList subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, long a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, long a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, long a[], int offset, int length );
|
|
+ /**
|
|
+ * @see List#add(Object)
|
|
+ */
|
|
+ boolean add( long key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ void add( int index, long key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, LongCollection c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, LongList c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( LongList c );
|
|
+ /**
|
|
+ * @see List#get(int)
|
|
+ */
|
|
+ long getLong( int index );
|
|
+ /**
|
|
+ * @see List#indexOf(Object)
|
|
+ */
|
|
+ int indexOf( long k );
|
|
+ /**
|
|
+ * @see List#lastIndexOf(Object)
|
|
+ */
|
|
+ int lastIndexOf( long k );
|
|
+ /**
|
|
+ * @see List#remove(int)
|
|
+ */
|
|
+ long removeLong( int index );
|
|
+ /**
|
|
+ * @see List#set(int,Object)
|
|
+ */
|
|
+ long set( int index, long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
|
|
new file mode 100644
|
|
index 0000000..e977a00
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
|
|
@@ -0,0 +1,85 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface LongListIterator extends ListIterator<Long>, LongBidirectionalIterator {
|
|
+ void set( long k );
|
|
+ void add( long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
|
|
new file mode 100644
|
|
index 0000000..cff8a3c
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
|
|
@@ -0,0 +1,334 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+import java.util.Collection;
|
|
+import java.util.Random;
|
|
+/** A class providing static methods and objects that do useful things with type-specific lists.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongLists {
|
|
+ private LongLists() {}
|
|
+ /** Shuffles the specified list using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param l the list to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>l</code>.
|
|
+ */
|
|
+ public static LongList shuffle( final LongList l, final Random random ) {
|
|
+ for( int i = l.size(); i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final long t = l.getLong( i );
|
|
+ l.set( i, l.getLong( p ) );
|
|
+ l.set( p, t );
|
|
+ }
|
|
+ return l;
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class EmptyList extends LongCollections.EmptyCollection implements LongList , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyList() {}
|
|
+ public void add( final int index, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long removeLong( int i ) { throw new UnsupportedOperationException(); }
|
|
+ public long set( final int index, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( long k ) { return -1; }
|
|
+ public int lastIndexOf( long k ) { return -1; }
|
|
+ public boolean addAll( Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public Long get( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( LongList c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, LongList c ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int index, final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long set( final int index, final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long getLong( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public Long remove( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( Object k ) { return -1; }
|
|
+ public int lastIndexOf( Object k ) { return -1; }
|
|
+ //SUPPRESS_WARNINGS_KEY_UNCHECKED
|
|
+ //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+
|
|
+ public LongIterator longIterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator listIterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator listIterator( int i ) { if ( i == 0 ) return LongIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( int i ) { return listIterator( i ); }
|
|
+ public LongList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( int from, int to ) { return subList( from, to ); }
|
|
+ public void getElements( int from, long[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
|
|
+ public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( int s ) { throw new UnsupportedOperationException(); }
|
|
+ public int compareTo( final List<? extends Long> o ) {
|
|
+ if ( o == this ) return 0;
|
|
+ return ((List<?>)o).isEmpty() ? 0 : -1;
|
|
+ }
|
|
+ private Object readResolve() { return EMPTY_LIST; }
|
|
+ public Object clone() { return EMPTY_LIST; }
|
|
+ public int hashCode() { return 1; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
|
|
+ public String toString() { return "[]"; }
|
|
+ }
|
|
+ /** An empty list (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptyList EMPTY_LIST = new EmptyList();
|
|
+ /** An immutable class representing a type-specific singleton list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class Singleton extends AbstractLongList implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private final long element;
|
|
+ private Singleton( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public long getLong( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
|
|
+ public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final long k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final Collection <? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public long[] toLongArray() {
|
|
+ long a[] = new long[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public LongListIterator listIterator() { return LongIterators.singleton( element ); }
|
|
+ public LongListIterator iterator() { return listIterator(); }
|
|
+ public LongListIterator listIterator( int i ) {
|
|
+ if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
|
|
+ LongListIterator l = listIterator();
|
|
+ if ( i == 1 ) l.next();
|
|
+ return l;
|
|
+ }
|
|
+
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( from != 0 || to != 1 ) return EMPTY_LIST;
|
|
+ return this;
|
|
+ }
|
|
+ public int size() { return 1; }
|
|
+ public void size( final int size ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return this; }
|
|
+ public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongList singleton( final long element ) { return new Singleton ( element ); }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongList singleton( final Object element ) { return new Singleton ( ((((Long)(element)).longValue())) ); }
|
|
+ /** A synchronized wrapper class for lists. */
|
|
+ public static class SynchronizedList extends LongCollections.SynchronizedCollection implements LongList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected SynchronizedList( final LongList l, final Object sync ) {
|
|
+ super( l, sync );
|
|
+ this.list = l;
|
|
+ }
|
|
+ protected SynchronizedList( final LongList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public long getLong( final int i ) { synchronized( sync ) { return list.getLong( i ); } }
|
|
+ public long set( final int i, final long k ) { synchronized( sync ) { return list.set( i, k ); } }
|
|
+ public void add( final int i, final long k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public long removeLong( final int i ) { synchronized( sync ) { return list.removeLong( i ); } }
|
|
+ public int indexOf( final long k ) { synchronized( sync ) { return list.indexOf( k ); } }
|
|
+ public int lastIndexOf( final long k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public void getElements( final int from, final long a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
|
|
+ public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
|
|
+ public void addElements( int index, final long a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
|
|
+ public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
|
|
+ public LongListIterator iterator() { return list.listIterator(); }
|
|
+ public LongListIterator listIterator() { return list.listIterator(); }
|
|
+ public LongListIterator listIterator( final int i ) { return list.listIterator( i ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
|
|
+ public LongList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ public int compareTo( final List<? extends Long> o ) { synchronized( sync ) { return list.compareTo( o ); } }
|
|
+ public boolean addAll( final int index, final LongCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public boolean addAll( final int index, LongList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
|
|
+ public boolean addAll( LongList l ) { synchronized( sync ) { return list.addAll( l ); } }
|
|
+ public Long get( final int i ) { synchronized( sync ) { return list.get( i ); } }
|
|
+ public void add( final int i, Long k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public Long set( final int index, Long k ) { synchronized( sync ) { return list.set( index, k ); } }
|
|
+ public Long remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
|
|
+ public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
|
|
+ public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static LongList synchronize( final LongList l ) { return new SynchronizedList ( l ); }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @param sync an object that will be used to synchronize the access to the list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static LongList synchronize( final LongList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
|
|
+ /** An unmodifiable wrapper class for lists. */
|
|
+ public static class UnmodifiableList extends LongCollections.UnmodifiableCollection implements LongList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected UnmodifiableList( final LongList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public long getLong( final int i ) { return list.getLong( i ); }
|
|
+ public long set( final int i, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int i, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final long k ) { return list.indexOf( k ); }
|
|
+ public int lastIndexOf( final long k ) { return list.lastIndexOf( k ); }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void getElements( final int from, final long a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
|
|
+ public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( final int size ) { list.size( size ); }
|
|
+ public LongListIterator iterator() { return listIterator(); }
|
|
+ public LongListIterator listIterator() { return LongIterators.unmodifiable( list.listIterator() ); }
|
|
+ public LongListIterator listIterator( final int i ) { return LongIterators.unmodifiable( list.listIterator( i ) ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
|
|
+ public LongList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ public int compareTo( final List<? extends Long> o ) { return list.compareTo( o ); }
|
|
+ public boolean addAll( final int index, final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongList l ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int index, final LongList l ) { throw new UnsupportedOperationException(); }
|
|
+ public Long get( final int i ) { return list.get( i ); }
|
|
+ public void add( final int i, Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long set( final int index, Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long remove( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final Object o ) { return list.indexOf( o ); }
|
|
+ public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in an unmodifiable list.
|
|
+ * @return an unmodifiable view of the specified list.
|
|
+ * @see java.util.Collections#unmodifiableList(List)
|
|
+ */
|
|
+ public static LongList unmodifiable( final LongList l ) { return new UnmodifiableList ( l ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
|
|
new file mode 100644
|
|
index 0000000..b6a8b42
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
|
|
@@ -0,0 +1,661 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific hash set with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class LongOpenCustomHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The hash strategy of this custom set. */
|
|
+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+
|
|
+ public LongOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongCollection c, final float f, it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongCollection c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongIterator i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f, strategy );
|
|
+ while( i.hasNext() ) add( i.nextLong() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongIterator i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( LongIterators.asLongIterator( i ), f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( LongIterators.asLongIterator( i ), strategy );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( length < 0 ? 0 : length, f, strategy );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, 0, a.length, f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash set.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ containsNull = true;
|
|
+ key[ n ] = k;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** An iterator over a hash set. */
|
|
+ private class SetIterator extends AbstractLongIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the null key. */
|
|
+ boolean mustReturnNull = LongOpenCustomHashSet.this.containsNull;
|
|
+ /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNull ) {
|
|
+ mustReturnNull = false;
|
|
+ last = n;
|
|
+ return key[ n ];
|
|
+ }
|
|
+ final long key[] = LongOpenCustomHashSet.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ return wrapped.getLong( - pos - 1 );
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = LongOpenCustomHashSet.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ LongOpenCustomHashSet.this.containsNull = false;
|
|
+ LongOpenCustomHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ LongOpenCustomHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ }
|
|
+ public LongIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ }
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongOpenCustomHashSet clone() {
|
|
+ LongOpenCustomHashSet c;
|
|
+ try {
|
|
+ c = (LongOpenCustomHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += ( strategy.hashCode(key[ i ]) );
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final LongIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ long k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
|
|
new file mode 100644
|
|
index 0000000..bcafa3e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
|
|
@@ -0,0 +1,627 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * enlarged as needed by doubling its size when new entries are created, but it is <em>never</em> made
|
|
+ * smaller (even on a {@link #clear()}). A family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class LongOpenHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+
|
|
+ public LongOpenHashSet( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public LongOpenHashSet() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final Collection<? extends Long> c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final Collection<? extends Long> c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongCollection c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongCollection c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongIterator i, final float f ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f );
|
|
+ while( i.hasNext() ) add( i.nextLong() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongIterator i ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final Iterator<?> i, final float f ) {
|
|
+ this( LongIterators.asLongIterator( i ), f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ */
|
|
+ public LongOpenHashSet( final Iterator<?> i ) {
|
|
+ this( LongIterators.asLongIterator( i ) );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final int offset, final int length, final float f ) {
|
|
+ this( length < 0 ? 0 : length, f );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final int offset, final int length ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final float f ) {
|
|
+ this( a, 0, a.length, f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNull;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** An iterator over a hash set. */
|
|
+ private class SetIterator extends AbstractLongIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the null key. */
|
|
+ boolean mustReturnNull = LongOpenHashSet.this.containsNull;
|
|
+ /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNull ) {
|
|
+ mustReturnNull = false;
|
|
+ last = n;
|
|
+ return key[ n ];
|
|
+ }
|
|
+ final long key[] = LongOpenHashSet.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ return wrapped.getLong( - pos - 1 );
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = LongOpenHashSet.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ LongOpenHashSet.this.containsNull = false;
|
|
+ LongOpenHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ LongOpenHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ }
|
|
+ public LongIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ }
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongOpenHashSet clone() {
|
|
+ LongOpenHashSet c;
|
|
+ try {
|
|
+ c = (LongOpenHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final LongIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ long k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000..de4db2d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
|
|
@@ -0,0 +1,108 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface LongPriorityQueue extends PriorityQueue<Long> {
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue.
|
|
+ */
|
|
+ void enqueue( long x );
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long dequeueLong();
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long firstLong();
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long lastLong();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
|
|
+ *
|
|
+ * @see PriorityQueue#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000..88dfc23
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
|
|
@@ -0,0 +1,116 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with type-specific priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+public class LongPriorityQueues {
|
|
+ private LongPriorityQueues() {}
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+ public static class SynchronizedPriorityQueue implements LongPriorityQueue {
|
|
+ final protected LongPriorityQueue q;
|
|
+ final protected Object sync;
|
|
+ protected SynchronizedPriorityQueue( final LongPriorityQueue q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedPriorityQueue( final LongPriorityQueue q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public void enqueue( long x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public long dequeueLong() { synchronized( sync ) { return q.dequeueLong(); } }
|
|
+ public long firstLong() { synchronized( sync ) { return q.firstLong(); } }
|
|
+ public long lastLong() { synchronized( sync ) { return q.lastLong(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public LongComparator comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public void enqueue( Long x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public Long dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public Long first() { synchronized( sync ) { return q.first(); } }
|
|
+ public Long last() { synchronized( sync ) { return q.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static LongPriorityQueue synchronize( final LongPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static LongPriorityQueue synchronize( final LongPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
|
|
new file mode 100644
|
|
index 0000000..c7dad79
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
|
|
@@ -0,0 +1,97 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface LongSet extends LongCollection , Set<Long> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ LongIterator iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
|
|
new file mode 100644
|
|
index 0000000..de7e3da
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
|
|
@@ -0,0 +1,186 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongSets {
|
|
+ private LongSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet extends LongCollections.EmptyCollection implements LongSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton extends AbstractLongSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final long element;
|
|
+ protected Singleton( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final long k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public long[] toLongArray() {
|
|
+ long a[] = new long[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public LongListIterator iterator() { return LongIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSet singleton( final long element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSet singleton( final Long element ) {
|
|
+ return new Singleton ( ((element).longValue()) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet extends LongCollections.SynchronizedCollection implements LongSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final LongSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final LongSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final long k ) { synchronized( sync ) { return collection.remove( (Long.valueOf(k)) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static LongSet synchronize( final LongSet s ) { return new SynchronizedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static LongSet synchronize( final LongSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet extends LongCollections.UnmodifiableCollection implements LongSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final LongSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static LongSet unmodifiable( final LongSet s ) { return new UnmodifiableSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..7490285
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
|
|
@@ -0,0 +1,179 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface LongSortedSet extends LongSet , SortedSet<Long> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ LongBidirectionalIterator iterator( long fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongBidirectionalIterator longIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ LongBidirectionalIterator iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ LongSortedSet subSet( Long fromElement, Long toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ LongSortedSet headSet( Long toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ LongSortedSet tailSet( Long fromElement );
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
|
|
+ *
|
|
+ * @see SortedSet#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+ /**
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ LongSortedSet subSet( long fromElement, long toElement) ;
|
|
+ /**
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ LongSortedSet headSet( long toElement );
|
|
+ /**
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ LongSortedSet tailSet( long fromElement );
|
|
+ /**
|
|
+ * @see SortedSet#first()
|
|
+ */
|
|
+ long firstLong();
|
|
+ /**
|
|
+ * @see SortedSet#last()
|
|
+ */
|
|
+ long lastLong();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
|
|
new file mode 100644
|
|
index 0000000..73e7361
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
|
|
@@ -0,0 +1,280 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongSortedSets {
|
|
+ private LongSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet extends LongSets.EmptySet implements LongSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return iterator(); }
|
|
+
|
|
+ public LongBidirectionalIterator iterator( long from ) { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongSortedSet subSet( long from, long to ) { return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet headSet( long from ) { return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet tailSet( long to ) { return EMPTY_SET; }
|
|
+ public long firstLong() { throw new NoSuchElementException(); }
|
|
+ public long lastLong() { throw new NoSuchElementException(); }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ public LongSortedSet subSet( Long from, Long to ) { return EMPTY_SET; }
|
|
+ public LongSortedSet headSet( Long from ) { return EMPTY_SET; }
|
|
+ public LongSortedSet tailSet( Long to ) { return EMPTY_SET; }
|
|
+ public Long first() { throw new NoSuchElementException(); }
|
|
+ public Long last() { throw new NoSuchElementException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton extends LongSets.Singleton implements LongSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final LongComparator comparator;
|
|
+ private Singleton( final long element, final LongComparator comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final long element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final long k1, final long k2 ) {
|
|
+ return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public LongBidirectionalIterator iterator( long from ) {
|
|
+ LongBidirectionalIterator i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public LongComparator comparator() { return comparator; }
|
|
+
|
|
+ public LongSortedSet subSet( final long from, final long to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet headSet( final long to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet tailSet( final long from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public long firstLong() { return element; }
|
|
+ public long lastLong() { return element; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() { return (Long.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() { return (Long.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return subSet( ((from).longValue()), ((to).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet headSet( final Long to ) { return headSet( ((to).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet tailSet( final Long from ) { return tailSet( ((from).longValue()) ); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final long element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final long element, final LongComparator comparator ) {
|
|
+ return new Singleton ( element, comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final Object element ) {
|
|
+ return new Singleton( ((((Long)(element)).longValue())) );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final Object element, final LongComparator comparator ) {
|
|
+ return new Singleton( ((((Long)(element)).longValue())), comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet extends LongSets.SynchronizedSet implements LongSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongSortedSet sortedSet;
|
|
+ protected SynchronizedSortedSet( final LongSortedSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final LongSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public LongComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
|
|
+ public LongSortedSet headSet( final long to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
|
|
+ public LongSortedSet tailSet( final long from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
|
|
+ public LongBidirectionalIterator iterator() { return sortedSet.iterator(); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return sortedSet.iterator(); }
|
|
+ public long firstLong() { synchronized( sync ) { return sortedSet.firstLong(); } }
|
|
+ public long lastLong() { synchronized( sync ) { return sortedSet.lastLong(); } }
|
|
+ public Long first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public Long last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
|
|
+ public LongSortedSet headSet( final Long to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
|
|
+ public LongSortedSet tailSet( final Long from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet synchronize( final LongSortedSet s ) { return new SynchronizedSortedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet synchronize( final LongSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet extends LongSets.UnmodifiableSet implements LongSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongSortedSet sortedSet;
|
|
+ protected UnmodifiableSortedSet( final LongSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public LongComparator comparator() { return sortedSet.comparator(); }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
|
|
+ public LongSortedSet headSet( final long to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
|
|
+ public LongSortedSet tailSet( final long from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
|
|
+ public LongBidirectionalIterator iterator() { return LongIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return LongIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return iterator(); }
|
|
+ public long firstLong() { return sortedSet.firstLong(); }
|
|
+ public long lastLong() { return sortedSet.lastLong(); }
|
|
+ public Long first() { return sortedSet.first(); }
|
|
+ public Long last() { return sortedSet.last(); }
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
|
|
+ public LongSortedSet headSet( final Long to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
|
|
+ public LongSortedSet tailSet( final Long from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet unmodifiable( final LongSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
|
|
new file mode 100644
|
|
index 0000000..3627a64
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
|
|
@@ -0,0 +1,91 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ */
|
|
+public interface LongStack extends Stack<Long> {
|
|
+ /**
|
|
+ * @see Stack#push(Object)
|
|
+ */
|
|
+ void push( long k );
|
|
+ /**
|
|
+ * @see Stack#pop()
|
|
+ */
|
|
+ long popLong();
|
|
+ /**
|
|
+ * @see Stack#top()
|
|
+ */
|
|
+ long topLong();
|
|
+ /**
|
|
+ * @see Stack#peek(int)
|
|
+ */
|
|
+ long peekLong( int i );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/package.html b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
|
|
new file mode 100644
|
|
index 0000000..772ffd4
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
|
|
@@ -0,0 +1,12 @@
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
+<html>
|
|
+ <head>
|
|
+ <title>fastutil</title>
|
|
+ </head>
|
|
+
|
|
+ <body>
|
|
+
|
|
+ <P>Provides type-specific classes for long elements or keys.
|
|
+
|
|
+ </body>
|
|
+</html>
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..4828c8c
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
|
|
@@ -0,0 +1,90 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractObjectBidirectionalIterator <K> extends AbstractObjectIterator <K> implements ObjectBidirectionalIterator <K> {
|
|
+ protected AbstractObjectBidirectionalIterator() {}
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previous();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
|
|
new file mode 100644
|
|
index 0000000..bd437e7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
|
|
@@ -0,0 +1,175 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractObjectCollection <K> extends AbstractCollection<K> implements ObjectCollection <K> {
|
|
+ protected AbstractObjectCollection() {}
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends K> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends K> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract ObjectIterator <K> iterator();
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator <K> i = iterator();
|
|
+ int n = size();
|
|
+ Object k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.next();
|
|
+ if (this == k) s.append("(this collection)"); else
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
|
|
new file mode 100644
|
|
index 0000000..654db5f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
|
|
@@ -0,0 +1,93 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractObjectIterator <K> implements ObjectIterator <K> {
|
|
+ protected AbstractObjectIterator() {}
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) next();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
|
|
new file mode 100644
|
|
index 0000000..41303ac
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
|
|
@@ -0,0 +1,472 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractObjectList <K> extends AbstractObjectCollection <K> implements ObjectList <K>, Stack <K> {
|
|
+ protected AbstractObjectList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public K remove( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public K set( final int index, final K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends K> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends K> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends K> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectListIterator <K> objectListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectListIterator <K> objectListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public ObjectListIterator <K> iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractObjectList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = pos++ ); }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ AbstractObjectList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractObjectList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractObjectList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final Object k ) {
|
|
+ final ObjectListIterator <K> i = listIterator();
|
|
+ K e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.next();
|
|
+ if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final Object k ) {
|
|
+ ObjectListIterator <K> i = listIterator( size() );
|
|
+ K e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previous();
|
|
+ if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (null) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public ObjectList <K> subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new ObjectSubList <K>( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectList <K> objectSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ ObjectListIterator <K> i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.next();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final K a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final K a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final Object a[], int offset, int length ) {
|
|
+ ObjectListIterator <K> i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.next();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public int compareTo( final List<? extends K> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof ObjectList ) {
|
|
+ final ObjectListIterator <K> i1 = listIterator(), i2 = ((ObjectList <K>)l).listIterator();
|
|
+ int r;
|
|
+ K e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.next();
|
|
+ e2 = i2.next();
|
|
+ if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends K> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super K>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ ObjectIterator <K> i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ K k = i.next();
|
|
+ h = 31 * h + ( (k) == null ? 0 : (k).hashCode() );
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( K o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public K pop() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return remove( size() - 1 );
|
|
+ }
|
|
+ public K top() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return get( size() - 1 );
|
|
+ }
|
|
+ public K peek( int i ) {
|
|
+ return get( size() - 1 - i );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator <K> i = iterator();
|
|
+ int n = size();
|
|
+ K k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.next();
|
|
+ if (this == k) s.append("(this list)"); else
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class ObjectSubList <K> extends AbstractObjectList <K> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final ObjectList <K> l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public ObjectSubList( final ObjectList <K> l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends K> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public K get( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.get( from + index );
|
|
+ }
|
|
+ public K remove( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.remove( from + index );
|
|
+ }
|
|
+ public K set( int index, K k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final Object[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final K a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.get( from + ( last = pos++ ) ); }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.get( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectList <K> subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new ObjectSubList <K>( this, from, to );
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ int index = indexOf( o );
|
|
+ if ( index == -1 ) return false;
|
|
+ remove( index );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
|
|
new file mode 100644
|
|
index 0000000..b7de919
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
|
|
@@ -0,0 +1,87 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractObjectListIterator <K> extends AbstractObjectBidirectionalIterator <K> implements ObjectListIterator <K> {
|
|
+ protected AbstractObjectListIterator() {}
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( K k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( K k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
|
|
new file mode 100644
|
|
index 0000000..7bb6799
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
|
|
@@ -0,0 +1,102 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractObjectSet <K> extends AbstractObjectCollection <K> implements Cloneable, ObjectSet <K> {
|
|
+ protected AbstractObjectSet() {}
|
|
+ public abstract ObjectIterator <K> iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ ObjectIterator <K> i = iterator();
|
|
+ K k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.next(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += ( (k) == null ? 0 : (k).hashCode() );
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( Object k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..6712d6d
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
|
|
@@ -0,0 +1,79 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractObjectSortedSet <K> extends AbstractObjectSet <K> implements ObjectSortedSet <K> {
|
|
+ protected AbstractObjectSortedSet() {}
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract ObjectBidirectionalIterator <K> iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
|
|
new file mode 100644
|
|
index 0000000..bce9171
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
|
|
@@ -0,0 +1,510 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling the current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible.
|
|
+ *
|
|
+ * <p>The backing array is exposed by the {@link #elements()} method. If an instance
|
|
+ * of this class was created {@linkplain #wrap(Object[],int) by wrapping},
|
|
+ * backing-array reallocations will be performed using reflection, so that
|
|
+ * {@link #elements()} can return an array of the same type of the original array: the comments
|
|
+ * about efficiency made in {@link it.unimi.dsi.fastutil.objects.ObjectArrays} apply here.
|
|
+ * Moreover, you must take into consideration that assignment to an array
|
|
+ * not of type {@code Object[]} is slower due to type checking.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class ObjectArrayList <K> extends AbstractObjectList <K> implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353131L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** Whether the backing array was passed to <code>wrap()</code>. In
|
|
+ * this case, we must reallocate with the same type of array. */
|
|
+ protected final boolean wrapped;
|
|
+ /** The backing array. */
|
|
+ protected transient K a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected ObjectArrayList( final K a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ this.wrapped = true;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = (K[]) new Object[ capacity ];
|
|
+ wrapped = false;
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public ObjectArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final Collection<? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ size = ObjectIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectCollection <? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ size = ObjectIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectList <? extends K> l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final K a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public ObjectArrayList( final K a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final Iterator<? extends K> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectIterator <? extends K> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * <P>If this array list was created by wrapping a given array, it is guaranteed
|
|
+ * that the type of the returned array will be the same. Otherwise, the returned
|
|
+ * array will be of type {@link Object Object[]} (in spite of the declared return type).
|
|
+ *
|
|
+ * <P><strong>Warning</strong>: This behaviour may cause (unfathomable)
|
|
+ * run-time errors if a method expects an array
|
|
+ * actually of type <code>K[]</code>, but this methods returns an array
|
|
+ * of type {@link Object Object[]}.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public K[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static <K> ObjectArrayList <K> wrap( final K a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final ObjectArrayList <K> l = new ObjectArrayList <K>( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static <K> ObjectArrayList <K> wrap( final K a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ if ( wrapped ) a = ObjectArrays.ensureCapacity( a, capacity, size );
|
|
+ else {
|
|
+ if ( capacity > a.length ) {
|
|
+ final Object t[] = new Object[ capacity ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = (K[])t;
|
|
+ }
|
|
+ }
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void grow( final int capacity ) {
|
|
+ if ( wrapped ) a = ObjectArrays.grow( a, capacity, size );
|
|
+ else {
|
|
+ if ( capacity > a.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * a.length, it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE ), capacity );
|
|
+ final Object t[] = new Object[ newLength ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = (K[])t;
|
|
+ }
|
|
+ }
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public K get( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final Object k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final Object k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public K remove( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final K old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ a[ size ] = null;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final Object k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ remove( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( o );
|
|
+ }
|
|
+ public K set( final int index, final K k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ K old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Arrays.fill( a, 0, size, null );
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (null) );
|
|
+ else Arrays.fill( a, size, this.size, (null) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final K t[] = (K[]) new Object[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final Object[] a, final int offset, final int length ) {
|
|
+ ObjectArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ int i = to - from;
|
|
+ while( i-- != 0 ) a[ size + i ] = null;
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final K a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ ObjectArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final Object[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ Arrays.fill( a, j, size, null );
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ ObjectArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectArrayList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectArrayList <K> clone() {
|
|
+ ObjectArrayList <K> c = new ObjectArrayList <K>( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ private boolean valEquals( final K a, final K b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final ObjectArrayList <K> l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final K[] a1 = a;
|
|
+ final K[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( ! valEquals( a1[ s ], a2[ s ] ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public int compareTo( final ObjectArrayList <? extends K> l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final K a1[] = a, a2[] = l.a;
|
|
+ K e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = (K[]) new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = (K) s.readObject();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
|
|
new file mode 100644
|
|
index 0000000..8b8dd8e
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
|
|
@@ -0,0 +1,220 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class ObjectArraySet <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient Object[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public ObjectArraySet( final Object[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public ObjectArraySet() {
|
|
+ this.a = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public ObjectArraySet( final int capacity ) {
|
|
+ this.a = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public ObjectArraySet( ObjectCollection <K> c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public ObjectArraySet( final Collection<? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public ObjectArraySet( final Object[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final Object o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == null ? (o) == null : (a[ i ]).equals(o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectIterator <K> iterator() {
|
|
+ return new AbstractObjectIterator <K> () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return (K) a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ a[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final Object k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ a[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final K k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final Object[] b = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) a[ i ] = null;
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectArraySet <K> clone() {
|
|
+ ObjectArraySet <K> c;
|
|
+ try {
|
|
+ c = (ObjectArraySet <K>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readObject();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
|
|
new file mode 100644
|
|
index 0000000..e56a0f8
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
|
|
@@ -0,0 +1,1594 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.Comparator;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> if your array is not of type {@code Object[]},
|
|
+ * {@link #ensureCapacity(Object[],int,int)} and {@link #grow(Object[],int,int)}
|
|
+ * will use {@linkplain java.lang.reflect.Array#newInstance(Class,int) reflection}
|
|
+ * to preserve your array type. Reflection is <em>significantly slower</em> than using <code>new</code>.
|
|
+ * This phenomenon is particularly
|
|
+ * evident in the first growth phases of an array reallocated with doubling (or similar) logic.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class ObjectArrays {
|
|
+ private ObjectArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static Object[] EMPTY_ARRAY = {};
|
|
+ /** Creates a new array using a the given one as prototype.
|
|
+ *
|
|
+ * <P>This method returns a new array of the given length whose element
|
|
+ * are of the same class as of those of <code>prototype</code>. In case
|
|
+ * of an empty array, it tries to return {@link #EMPTY_ARRAY}, if possible.
|
|
+ *
|
|
+ * @param prototype an array that will be used to type the new one.
|
|
+ * @param length the length of the new array.
|
|
+ * @return a new array of given type and length.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> K[] newArray( final K[] prototype, final int length ) {
|
|
+ final Class<?> klass = prototype.getClass();
|
|
+ if ( klass == Object[].class ) return (K[])( length == 0 ? EMPTY_ARRAY : new Object[ length ] );
|
|
+ return (K[])java.lang.reflect.Array.newInstance( klass.getComponentType(), length );
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static <K> K[] ensureCapacity( final K[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final K t[] =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static <K> K[] ensureCapacity( final K[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final K t[] =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>array.length</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static <K> K[] grow( final K[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final K t[] =
|
|
+ newArray( array, newLength );
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length, preserving just a part of the array.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) entries whose first
|
|
+ * <code>preserve</code> entries are the same as those of <code>array</code>.
|
|
+ * */
|
|
+ public static <K> K[] grow( final K[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * array.length, Arrays.MAX_ARRAY_SIZE ), length );
|
|
+ final K t[] =
|
|
+ newArray( array, newLength );
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Trims the given array to the given length.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new maximum length for the array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code>
|
|
+ * entries or less; otherwise, an array with
|
|
+ * <code>length</code> entries whose entries are the same as
|
|
+ * the first <code>length</code> entries of <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static <K> K[] trim( final K[] array, final int length ) {
|
|
+ if ( length >= array.length ) return array;
|
|
+ final K t[] =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, 0, t, 0, length );
|
|
+ return t;
|
|
+ }
|
|
+ /** Sets the length of the given array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new length for the array.
|
|
+ * @return <code>array</code>, if it contains exactly <code>length</code>
|
|
+ * entries; otherwise, if it contains <em>more</em> than
|
|
+ * <code>length</code> entries, an array with <code>length</code> entries
|
|
+ * whose entries are the same as the first <code>length</code> entries of
|
|
+ * <code>array</code>; otherwise, an array with <code>length</code> entries
|
|
+ * whose first <code>array.length</code> entries are the same as those of
|
|
+ * <code>array</code>.
|
|
+ *
|
|
+ */
|
|
+ public static <K> K[] setLength( final K[] array, final int length ) {
|
|
+ if ( length == array.length ) return array;
|
|
+ if ( length < array.length ) return trim( array, length );
|
|
+ return ensureCapacity( array, length );
|
|
+ }
|
|
+ /** Returns a copy of a portion of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param offset the first element to copy.
|
|
+ * @param length the number of elements to copy.
|
|
+ * @return a new array containing <code>length</code> elements of <code>array</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static <K> K[] copy( final K[] array, final int offset, final int length ) {
|
|
+ ensureOffsetLength( array, offset, length );
|
|
+ final K[] a =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, offset, a, 0, length );
|
|
+ return a;
|
|
+ }
|
|
+ /** Returns a copy of an array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @return a copy of <code>array</code>.
|
|
+ */
|
|
+ public static <K> K[] copy( final K[] array ) {
|
|
+ return array.clone();
|
|
+ }
|
|
+ /** Fills the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param value the new value for all elements of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static <K> void fill( final K[] array, final K value ) {
|
|
+ int i = array.length;
|
|
+ while( i-- != 0 ) array[ i ] = value;
|
|
+ }
|
|
+ /** Fills a portion of the given array with the given value.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param from the starting index of the portion to fill (inclusive).
|
|
+ * @param to the end index of the portion to fill (exclusive).
|
|
+ * @param value the new value for all elements of the specified portion of the array.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static <K> void fill( final K[] array, final int from, int to, final K value ) {
|
|
+ ensureFromTo( array, from, to );
|
|
+ if ( from == 0 ) while( to-- != 0 ) array[ to ] = value;
|
|
+ else for( int i = from; i < to; i++ ) array[ i ] = value;
|
|
+ }
|
|
+ /** Returns true if the two arrays are elementwise equal.
|
|
+ *
|
|
+ * @param a1 an array.
|
|
+ * @param a2 another array.
|
|
+ * @return true if the two arrays are of the same length, and their elements are equal.
|
|
+ * @deprecated Please use the corresponding {@link java.util.Arrays} method, which is intrinsified in recent JVMs.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public static <K> boolean equals( final K[] a1, final K a2[] ) {
|
|
+ int i = a1.length;
|
|
+ if ( i != a2.length ) return false;
|
|
+ while( i-- != 0 ) if (! ( (a1[ i ]) == null ? (a2[ i ]) == null : (a1[ i ]).equals(a2[ i ]) ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param from a start index (inclusive).
|
|
+ * @param to an end index (exclusive).
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than the array length or negative.
|
|
+ */
|
|
+ public static <K> void ensureFromTo( final K[] a, final int from, final int to ) {
|
|
+ Arrays.ensureFromTo( a.length, from, to );
|
|
+ }
|
|
+ /** Ensures that a range given by an offset and a length fits an array.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param offset a start index.
|
|
+ * @param length a length (the number of elements in the range).
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than the array length.
|
|
+ */
|
|
+ public static <K> void ensureOffsetLength( final K[] a, final int offset, final int length ) {
|
|
+ Arrays.ensureOffsetLength( a.length, offset, length );
|
|
+ }
|
|
+ /** Ensures that two arrays are of the same length.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param b another array.
|
|
+ * @throws IllegalArgumentException if the two argument arrays are not of the same length.
|
|
+ */
|
|
+ public static <K> void ensureSameLength( final K[] a, final K[] b ) {
|
|
+ if ( a.length != b.length ) throw new IllegalArgumentException( "Array size mismatch: " + a.length + " != " + b.length );
|
|
+ }
|
|
+ private static final int QUICKSORT_NO_REC = 16;
|
|
+ private static final int PARALLEL_QUICKSORT_NO_FORK = 8192;
|
|
+ private static final int QUICKSORT_MEDIAN_OF_9 = 128;
|
|
+ private static final int MERGESORT_NO_REC = 16;
|
|
+ /** Swaps two elements of an anrray.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ */
|
|
+ public static <K> void swap( final K x[], final int a, final int b ) {
|
|
+ final K t = x[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ x[ b ] = t;
|
|
+ }
|
|
+ /** Swaps two sequences of elements of an array.
|
|
+ *
|
|
+ * @param x an array.
|
|
+ * @param a a position in {@code x}.
|
|
+ * @param b another position in {@code x}.
|
|
+ * @param n the number of elements to exchange starting at {@code a} and {@code b}.
|
|
+ */
|
|
+ public static <K> void swap( final K[] x, int a, int b, final int n ) {
|
|
+ for( int i = 0; i < n; i++, a++, b++ ) swap( x, a, b );
|
|
+ }
|
|
+ private static <K> int med3( final K x[], final int a, final int b, final int c, Comparator <K> comp ) {
|
|
+ final int ab = comp.compare( x[ a ], x[ b ] );
|
|
+ final int ac = comp.compare( x[ a ], x[ c ] );
|
|
+ final int bc = comp.compare( x[ b ], x[ c ] );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static <K> void selectionSort( final K[] a, final int from, final int to, final Comparator <K> comp ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( comp.compare( a[ j ], a[ m ] ) < 0 ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final K u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ private static <K> void insertionSort( final K[] a, final int from, final int to, final Comparator <K> comp ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ K t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( K u = a[ j - 1 ]; comp.compare( t, u ) < 0; u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static <K> void quickSort( final K[] x, final int from, final int to, final Comparator <K> comp ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s, comp );
|
|
+ m = med3( x, m - s, m, m + s, comp );
|
|
+ n = med3( x, n - 2 * s, n - s, n, comp );
|
|
+ }
|
|
+ m = med3( x, l, m, n, comp ); // Mid-size, med of 3
|
|
+ final K v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s, comp );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to, comp );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ *
|
|
+ */
|
|
+ public static <K> void quickSort( final K[] x, final Comparator <K> comp ) {
|
|
+ quickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortComp <K> extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final K[] x;
|
|
+ private final Comparator <K> comp;
|
|
+ public ForkJoinQuickSortComp( final K[] x , final int from , final int to, final Comparator <K> comp ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.comp = comp;
|
|
+ }
|
|
+ @Override
|
|
+ protected void compute() {
|
|
+ final K[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final K v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = comp.compare( x[ b ], v ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = comp.compare( x[ c ], v ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortComp <K>( x, from, from + s, comp ), new ForkJoinQuickSortComp <K>( x, to - t, to, comp ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortComp <K>( x, from, from + s, comp ) );
|
|
+ else invokeAll( new ForkJoinQuickSortComp <K>( x, to - t, to, comp ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x, final int from, final int to, final Comparator <K> comp ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to, comp );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortComp <K>( x, from, to, comp ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x, final Comparator <K> comp ) {
|
|
+ parallelQuickSort( x, 0, x.length, comp );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> int med3( final K x[], final int a, final int b, final int c ) {
|
|
+ final int ab = ( ((Comparable<K>)(x[ a ])).compareTo(x[ b ]) );
|
|
+ final int ac = ( ((Comparable<K>)(x[ a ])).compareTo(x[ c ]) );
|
|
+ final int bc = ( ((Comparable<K>)(x[ b ])).compareTo(x[ c ]) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> void selectionSort( final K[] a, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i;
|
|
+ for( int j = i + 1; j < to; j++ ) if ( ( ((Comparable<K>)(a[ j ])).compareTo(a[ m ]) < 0 ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ final K u = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = u;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> void insertionSort( final K[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ K t = a[ i ];
|
|
+ int j = i;
|
|
+ for ( K u = a[ j - 1 ]; ( ((Comparable<K>)(t)).compareTo(u) < 0 ); u = a[ --j - 1 ] ) {
|
|
+ a[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ a[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> void quickSort( final K[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, l, m, n ); // Mid-size, med of 3
|
|
+ final K v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static <K> void quickSort( final K[] x ) {
|
|
+ quickSort( x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort <K> extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final K[] x;
|
|
+ public ForkJoinQuickSort( final K[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void compute() {
|
|
+ final K[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, l, l + s, l + 2 * s );
|
|
+ m = med3( x, m - s, m, m + s );
|
|
+ n = med3( x, n - 2 * s, n - s, n );
|
|
+ m = med3( x, l, m, n );
|
|
+ final K v = x[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort <K>( x, from, from + s ), new ForkJoinQuickSort <K>( x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort <K>( x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort <K>( x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort <K>( x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x ) {
|
|
+ parallelQuickSort( x, 0, x.length );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> int med3Indirect( final int perm[], final K x[], final int a, final int b, final int c ) {
|
|
+ final K aa = x[ perm[ a ] ];
|
|
+ final K bb = x[ perm[ b ] ];
|
|
+ final K cc = x[ perm[ c ] ];
|
|
+ final int ab = ( ((Comparable<K>)(aa)).compareTo(bb) );
|
|
+ final int ac = ( ((Comparable<K>)(aa)).compareTo(cc) );
|
|
+ final int bc = ( ((Comparable<K>)(bb)).compareTo(cc) );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> void insertionSortIndirect( final int[] perm, final K[] a, final int from, final int to ) {
|
|
+ for ( int i = from; ++i < to; ) {
|
|
+ int t = perm[ i ];
|
|
+ int j = i;
|
|
+ for ( int u = perm[ j - 1 ]; ( ((Comparable<K>)(a[ t ])).compareTo(a[ u ]) < 0 ); u = perm[ --j - 1 ] ) {
|
|
+ perm[ j ] = u;
|
|
+ if ( from == j - 1 ) {
|
|
+ --j;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ perm[ j ] = t;
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> void quickSortIndirect( final int[] perm, final K[] x, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ // Selection sort on smallest arrays
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ insertionSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3Indirect( perm, x, l, m, n ); // Mid-size, med of 3
|
|
+ final K v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while(true) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while (c >= b && ( comparison = ( ((Comparable<K>)(x[ perm[ c ] ])).compareTo(v) ) ) >=0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSortIndirect( perm, x, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSortIndirect( perm, x, to - s, to );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>Note that this implementation does not allocate any object, contrarily to the implementation
|
|
+ * used to sort primitive types in {@link java.util.Arrays}, which switches to mergesort on large inputs.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ */
|
|
+ public static <K> void quickSortIndirect( final int perm[], final K[] x ) {
|
|
+ quickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSortIndirect <K> extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final int[] perm;
|
|
+ private final K[] x;
|
|
+ public ForkJoinQuickSortIndirect( final int perm[], final K[] x , final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.perm = perm;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void compute() {
|
|
+ final K[] x = this.x;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSortIndirect( perm, x, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3Indirect( perm, x, l, l + s, l + 2 * s );
|
|
+ m = med3Indirect( perm, x, m - s, m, m + s );
|
|
+ n = med3Indirect( perm, x, n - 2 * s, n - s, n );
|
|
+ m = med3Indirect( perm, x, l, m, n );
|
|
+ final K v = x[ perm[ m ] ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison;
|
|
+ while ( b <= c && ( comparison = ( ((Comparable<K>)(x[ perm[ b ] ])).compareTo(v) ) ) <= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( ((Comparable<K>)(x[ perm[ c ] ])).compareTo(v) ) ) >= 0 ) {
|
|
+ if ( comparison == 0 ) IntArrays.swap( perm, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ IntArrays.swap( perm, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ IntArrays.swap( perm, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ IntArrays.swap( perm, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, from, from + s ), new ForkJoinQuickSortIndirect <K>( perm, x, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSortIndirect <K>( perm, x, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static <K> void parallelQuickSortIndirect( final int[] perm, final K[] x, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSortIndirect( perm, x, from, to );
|
|
+ else {
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSortIndirect <K>( perm, x, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using a parallel indirect quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implement an <em>indirect</em> sort. The elements of <code>perm</code> (which must
|
|
+ * be exactly the numbers in the interval <code>[0..perm.length)</code>) will be permuted so that
|
|
+ * <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x}.
|
|
+ * @param x the array to be sorted.
|
|
+ *
|
|
+ */
|
|
+ public static <K> void parallelQuickSortIndirect( final int perm[], final K[] x ) {
|
|
+ parallelQuickSortIndirect( perm, x, 0, x.length );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ * @param from the index of the first element (inclusive) to be stabilized.
|
|
+ * @param to the index of the last element (exclusive) to be stabilized.
|
|
+ */
|
|
+ public static <K> void stabilize( final int perm[], final K[] x, final int from, final int to ) {
|
|
+ int curr = from;
|
|
+ for( int i = from + 1; i < to; i++ ) {
|
|
+ if ( x[ perm[ i ] ] != x[ perm[ curr ] ] ) {
|
|
+ if ( i - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, i );
|
|
+ curr = i;
|
|
+ }
|
|
+ }
|
|
+ if ( to - curr > 1 ) IntArrays.parallelQuickSort( perm, curr, to );
|
|
+ }
|
|
+ /** Stabilizes a permutation.
|
|
+ *
|
|
+ * <p>This method can be used to stabilize the permutation generated by an indirect sorting, assuming that
|
|
+ * initially the permutation array was in ascending order (e.g., the identity, as usually happens). This method
|
|
+ * scans the permutation, and for each non-singleton block of elements with the same associated values in {@code x},
|
|
+ * permutes them in ascending order. The resulting permutation corresponds to a stable sort.
|
|
+ *
|
|
+ * <p>Usually combining an unstable indirect sort and this method is more efficient than using a stable sort,
|
|
+ * as most stable sort algorithms require a support array.
|
|
+ *
|
|
+ * <p>More precisely, assuming that <code>x[ perm[ i ] ] ≤ x[ perm[ i + 1 ] ]</code>, after
|
|
+ * stabilization we will also have that <code>x[ perm[ i ] ] = x[ perm[ i + 1 ] ]</code> implies
|
|
+ * <code>perm[ i ] ≤ perm[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param perm a permutation array indexing {@code x} so that it is sorted.
|
|
+ * @param x the sorted array to be stabilized.
|
|
+ */
|
|
+ public static <K> void stabilize( final int perm[], final K[] x ) {
|
|
+ stabilize( perm, x, 0, perm.length );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> int med3( final K x[], final K[] y, final int a, final int b, final int c ) {
|
|
+ int t;
|
|
+ final int ab = ( t = ( ((Comparable<K>)(x[ a ])).compareTo(x[ b ]) ) ) == 0 ? ( ((Comparable<K>)(y[ a ])).compareTo(y[ b ]) ) : t;
|
|
+ final int ac = ( t = ( ((Comparable<K>)(x[ a ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable<K>)(y[ a ])).compareTo(y[ c ]) ) : t;
|
|
+ final int bc = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(x[ c ]) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(y[ c ]) ) : t;
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+ private static <K> void swap( final K x[], final K[] y, final int a, final int b ) {
|
|
+ final K t = x[ a ];
|
|
+ final K u = y[ a ];
|
|
+ x[ a ] = x[ b ];
|
|
+ y[ a ] = y[ b ];
|
|
+ x[ b ] = t;
|
|
+ y[ b ] = u;
|
|
+ }
|
|
+ private static <K> void swap( final K[] x, final K[] y, int a, int b, final int n ) {
|
|
+ for ( int i = 0; i < n; i++, a++, b++ ) swap( x, y, a, b );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> void selectionSort( final K[] a, final K[] b, final int from, final int to ) {
|
|
+ for( int i = from; i < to - 1; i++ ) {
|
|
+ int m = i, u;
|
|
+ for( int j = i + 1; j < to; j++ )
|
|
+ if ( ( u = ( ((Comparable<K>)(a[ j ])).compareTo(a[ m ]) ) ) < 0 || u == 0 && ( ((Comparable<K>)(b[ j ])).compareTo(b[ m ]) < 0 ) ) m = j;
|
|
+ if ( m != i ) {
|
|
+ K t = a[ i ];
|
|
+ a[ i ] = a[ m ];
|
|
+ a[ m ] = t;
|
|
+ t = b[ i ];
|
|
+ b[ i ] = b[ m ];
|
|
+ b[ m ] = t;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> void quickSort( final K[] x, final K[] y, final int from, final int to ) {
|
|
+ final int len = to - from;
|
|
+ if ( len < QUICKSORT_NO_REC ) {
|
|
+ selectionSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ if ( len > QUICKSORT_MEDIAN_OF_9 ) { // Big arrays, pseudomedian of 9
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ }
|
|
+ m = med3( x, y, l, m, n ); // Mid-size, med of 3
|
|
+ final K v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(w) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ c ])).compareTo(w) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int s;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( ( s = b - a ) > 1 ) quickSort( x, y, from, from + s );
|
|
+ if ( ( s = d - c ) > 1 ) quickSort( x, y, to - s, to );
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical ascending order using quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static <K> void quickSort( final K[] x, final K[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ quickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ protected static class ForkJoinQuickSort2 <K> extends RecursiveAction {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final int from;
|
|
+ private final int to;
|
|
+ private final K[] x, y;
|
|
+ public ForkJoinQuickSort2( final K[] x, final K[] y, final int from , final int to ) {
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ this.x = x;
|
|
+ this.y = y;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void compute() {
|
|
+ final K[] x = this.x;
|
|
+ final K[] y = this.y;
|
|
+ final int len = to - from;
|
|
+ if ( len < PARALLEL_QUICKSORT_NO_FORK ) {
|
|
+ quickSort( x, y, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Choose a partition element, v
|
|
+ int m = from + len / 2;
|
|
+ int l = from;
|
|
+ int n = to - 1;
|
|
+ int s = len / 8;
|
|
+ l = med3( x, y, l, l + s, l + 2 * s );
|
|
+ m = med3( x, y, m - s, m, m + s );
|
|
+ n = med3( x, y, n - 2 * s, n - s, n );
|
|
+ m = med3( x, y, l, m, n );
|
|
+ final K v = x[ m ], w = y[ m ];
|
|
+ // Establish Invariant: v* (<v)* (>v)* v*
|
|
+ int a = from, b = a, c = to - 1, d = c;
|
|
+ while ( true ) {
|
|
+ int comparison, t;
|
|
+ while ( b <= c && ( comparison = ( t = ( ((Comparable<K>)(x[ b ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ b ])).compareTo(w) ) : t ) <= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, a++, b );
|
|
+ b++;
|
|
+ }
|
|
+ while ( c >= b && ( comparison = ( t = ( ((Comparable<K>)(x[ c ])).compareTo(v) ) ) == 0 ? ( ((Comparable<K>)(y[ c ])).compareTo(w) ) : t ) >= 0 ) {
|
|
+ if ( comparison == 0 ) swap( x, y, c, d-- );
|
|
+ c--;
|
|
+ }
|
|
+ if ( b > c ) break;
|
|
+ swap( x, y, b++, c-- );
|
|
+ }
|
|
+ // Swap partition elements back to middle
|
|
+ int t;
|
|
+ s = Math.min( a - from, b - a );
|
|
+ swap( x, y, from, b - s, s );
|
|
+ s = Math.min( d - c, to - d - 1 );
|
|
+ swap( x, y, b, to - s, s );
|
|
+ s = b - a;
|
|
+ t = d - c;
|
|
+ // Recursively sort non-partition-elements
|
|
+ if ( s > 1 && t > 1 ) invokeAll( new ForkJoinQuickSort2 <K>( x, y, from, from + s ), new ForkJoinQuickSort2 <K>( x, y, to - t, to ) );
|
|
+ else if ( s > 1 ) invokeAll( new ForkJoinQuickSort2 <K>( x, y, from, from + s ) );
|
|
+ else invokeAll( new ForkJoinQuickSort2 <K>( x, y, to - t, to ) );
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements of two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x, final K[] y, final int from, final int to ) {
|
|
+ if ( to - from < PARALLEL_QUICKSORT_NO_FORK ) quickSort( x, y, from, to );
|
|
+ final ForkJoinPool pool = new ForkJoinPool( Runtime.getRuntime().availableProcessors() );
|
|
+ pool.invoke( new ForkJoinQuickSort2 <K>( x, y, from, to ) );
|
|
+ pool.shutdown();
|
|
+ }
|
|
+ /** Sorts two arrays according to the natural lexicographical
|
|
+ * ascending order using a parallel quicksort.
|
|
+ *
|
|
+ * <p>The sorting algorithm is a tuned quicksort adapted from Jon L. Bentley and M. Douglas
|
|
+ * McIlroy, “Engineering a Sort Function”, <i>Software: Practice and Experience</i>, 23(11), pages
|
|
+ * 1249−1265, 1993.
|
|
+ *
|
|
+ * <p>This method implements a <em>lexicographical</em> sorting of the arguments. Pairs of
|
|
+ * elements in the same position in the two provided arrays will be considered a single key, and
|
|
+ * permuted accordingly. In the end, either <code>x[ i ] < x[ i + 1 ]</code> or <code>x[ i ]
|
|
+ * == x[ i + 1 ]</code> and <code>y[ i ] ≤ y[ i + 1 ]</code>.
|
|
+ *
|
|
+ * <p>This implementation uses a {@link ForkJoinPool} executor service with
|
|
+ * {@link Runtime#availableProcessors()} parallel threads.
|
|
+ *
|
|
+ * @param x the first array to be sorted.
|
|
+ * @param y the second array to be sorted.
|
|
+ */
|
|
+ public static <K> void parallelQuickSort( final K[] x, final K[] y ) {
|
|
+ ensureSameLength( x, y );
|
|
+ parallelQuickSort( x, y, 0, x.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> void mergeSort( final K a[], final int from, final int to, final K supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, a );
|
|
+ mergeSort( supp, mid, to, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( ( ((Comparable<K>)(supp[ mid - 1 ])).compareTo(supp[ mid ]) <= 0 ) ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && ( ((Comparable<K>)(supp[ p ])).compareTo(supp[ q ]) <= 0 ) ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ */
|
|
+ public static <K> void mergeSort( final K a[], final int from, final int to ) {
|
|
+ mergeSort( a, from, to, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the natural ascending order using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ */
|
|
+ public static <K> void mergeSort( final K a[] ) {
|
|
+ mergeSort( a, 0, a.length );
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort, using a given pre-filled support array.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. Moreover, no support arrays will be allocated.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ * @param supp a support array containing at least <code>to</code> elements, and whose entries are identical to those
|
|
+ * of {@code a} in the specified range.
|
|
+ */
|
|
+ public static <K> void mergeSort( final K a[], final int from, final int to, Comparator <K> comp, final K supp[] ) {
|
|
+ int len = to - from;
|
|
+ // Insertion sort on smallest arrays
|
|
+ if ( len < MERGESORT_NO_REC ) {
|
|
+ insertionSort( a, from, to, comp );
|
|
+ return;
|
|
+ }
|
|
+ // Recursively sort halves of a into supp
|
|
+ final int mid = ( from + to ) >>> 1;
|
|
+ mergeSort( supp, from, mid, comp, a );
|
|
+ mergeSort( supp, mid, to, comp, a );
|
|
+ // If list is already sorted, just copy from supp to a. This is an
|
|
+ // optimization that results in faster sorts for nearly ordered lists.
|
|
+ if ( comp.compare( supp[ mid - 1 ], supp[ mid ] ) <= 0 ) {
|
|
+ System.arraycopy( supp, from, a, from, len );
|
|
+ return;
|
|
+ }
|
|
+ // Merge sorted halves (now in supp) into a
|
|
+ for( int i = from, p = from, q = mid; i < to; i++ ) {
|
|
+ if ( q >= to || p < mid && comp.compare( supp[ p ], supp[ q ] ) <= 0 ) a[ i ] = supp[ p++ ];
|
|
+ else a[ i ] = supp[ q++ ];
|
|
+ }
|
|
+ }
|
|
+ /** Sorts the specified range of elements according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+ *
|
|
+ * @param a the array to be sorted.
|
|
+ * @param from the index of the first element (inclusive) to be sorted.
|
|
+ * @param to the index of the last element (exclusive) to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static <K> void mergeSort( final K a[], final int from, final int to, Comparator <K> comp ) {
|
|
+ mergeSort( a, from, to, comp, a.clone() );
|
|
+ }
|
|
+ /** Sorts an array according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. An array as large as <code>a</code> will be allocated by this method.
|
|
+
|
|
+ * @param a the array to be sorted.
|
|
+ * @param comp the comparator to determine the sorting order.
|
|
+ */
|
|
+ public static <K> void mergeSort( final K a[], Comparator <K> comp ) {
|
|
+ mergeSort( a, 0, a.length, comp );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> int binarySearch( final K[] a, int from, int to, final K key ) {
|
|
+ K midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ final int cmp = ((Comparable <? super K>)midVal).compareTo( key );
|
|
+ if ( cmp < 0 ) from = mid + 1;
|
|
+ else if (cmp > 0) to = mid - 1;
|
|
+ else return mid;
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm. The range must be sorted prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static <K> int binarySearch( final K[] a, final K key ) {
|
|
+ return binarySearch( a, 0, a.length, key );
|
|
+ }
|
|
+ /**
|
|
+ * Searches a range of the specified array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param from the index of the first element (inclusive) to be searched.
|
|
+ * @param to the index of the last element (exclusive) to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static <K> int binarySearch( final K[] a, int from, int to, final K key, final Comparator <K> c ) {
|
|
+ K midVal;
|
|
+ to--;
|
|
+ while (from <= to) {
|
|
+ final int mid = (from + to) >>> 1;
|
|
+ midVal = a[ mid ];
|
|
+ final int cmp = c.compare( midVal, key );
|
|
+ if ( cmp < 0 ) from = mid + 1;
|
|
+ else if (cmp > 0) to = mid - 1;
|
|
+ else return mid; // key found
|
|
+ }
|
|
+ return -( from + 1 );
|
|
+ }
|
|
+ /**
|
|
+ * Searches an array for the specified value using
|
|
+ * the binary search algorithm and a specified comparator. The range must be sorted following the comparator prior to making this call.
|
|
+ * If it is not sorted, the results are undefined. If the range contains multiple elements with
|
|
+ * the specified value, there is no guarantee which one will be found.
|
|
+ *
|
|
+ * @param a the array to be searched.
|
|
+ * @param key the value to be searched for.
|
|
+ * @param c a comparator.
|
|
+ * @return index of the search key, if it is contained in the array;
|
|
+ * otherwise, <code>(-(<i>insertion point</i>) - 1)</code>. The <i>insertion
|
|
+ * point</i> is defined as the the point at which the value would
|
|
+ * be inserted into the array: the index of the first
|
|
+ * element greater than the key, or the length of the array, if all
|
|
+ * elements in the array are less than the specified key. Note
|
|
+ * that this guarantees that the return value will be ≥ 0 if
|
|
+ * and only if the key is found.
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+ public static <K> int binarySearch( final K[] a, final K key, final Comparator <K> c ) {
|
|
+ return binarySearch( a, 0, a.length, key, c );
|
|
+ }
|
|
+ /** Shuffles the specified array fragment using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param from the index of the first element (inclusive) to be shuffled.
|
|
+ * @param to the index of the last element (exclusive) to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static <K> K[] shuffle( final K[] a, final int from, final int to, final Random random ) {
|
|
+ for( int i = to - from; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final K t = a[ from + i ];
|
|
+ a[ from + i ] = a[ from + p ];
|
|
+ a[ from + p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Shuffles the specified array using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param a the array to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static <K> K[] shuffle( final K[] a, final Random random ) {
|
|
+ for( int i = a.length; i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final K t = a[ i ];
|
|
+ a[ i ] = a[ p ];
|
|
+ a[ p ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static <K> K[] reverse( final K[] a ) {
|
|
+ final int length = a.length;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final K t = a[ length - i - 1 ];
|
|
+ a[ length - i - 1 ] = a[ i ];
|
|
+ a[ i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** Reverses the order of the elements in the specified array fragment.
|
|
+ *
|
|
+ * @param a the array to be reversed.
|
|
+ * @param from the index of the first element (inclusive) to be reversed.
|
|
+ * @param to the index of the last element (exclusive) to be reversed.
|
|
+ * @return <code>a</code>.
|
|
+ */
|
|
+ public static <K> K[] reverse( final K[] a, final int from, final int to ) {
|
|
+ final int length = to - from;
|
|
+ for( int i = length / 2; i-- != 0; ) {
|
|
+ final K t = a[ from + length - i - 1 ];
|
|
+ a[ from + length - i - 1 ] = a[ from + i ];
|
|
+ a[ from + i ] = t;
|
|
+ }
|
|
+ return a;
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays. */
|
|
+ private static final class ArrayHashStrategy <K> implements Hash.Strategy<K[]>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ public int hashCode( final K[] o ) {
|
|
+ return java.util.Arrays.hashCode( o );
|
|
+ }
|
|
+ public boolean equals( final K[] a, final K[] b ) {
|
|
+ return java.util.Arrays.equals( a, b );
|
|
+ }
|
|
+ }
|
|
+ /** A type-specific content-based hash strategy for arrays.
|
|
+ *
|
|
+ * <P>This hash strategy may be used in custom hash collections whenever keys are
|
|
+ * arrays, and they must be considered equal by content. This strategy
|
|
+ * will handle <code>null</code> correctly, and it is serializable.
|
|
+ */
|
|
+ @SuppressWarnings({"rawtypes"})
|
|
+ public final static Hash.Strategy HASH_STRATEGY = new ArrayHashStrategy();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000..2dc5150
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
|
|
@@ -0,0 +1,88 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface ObjectBidirectionalIterator <K> extends ObjectIterator <K>, BidirectionalIterator<K> {
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
|
|
new file mode 100644
|
|
index 0000000..e169594
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
|
|
@@ -0,0 +1,109 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface ObjectCollection <K> extends Collection<K>, ObjectIterable <K> {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ ObjectIterator <K> iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectIterator <K> objectIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
|
|
new file mode 100644
|
|
index 0000000..e6c2991
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
|
|
@@ -0,0 +1,212 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectCollections {
|
|
+ private ObjectCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection <K> extends AbstractObjectCollection <K> {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( Object k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ public <T> T[] toArray( T[] a ) { return a; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection <K> implements ObjectCollection <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectCollection <K> collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final ObjectCollection <K> c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final ObjectCollection <K> c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final Object o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public ObjectIterator <K> iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ public boolean add( final K k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final Object k ) { synchronized( sync ) { return collection.remove( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c ) { return new SynchronizedCollection <K>( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c, final Object sync ) { return new SynchronizedCollection <K>( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection <K> implements ObjectCollection <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectCollection <K> collection;
|
|
+ protected UnmodifiableCollection( final ObjectCollection <K> c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final Object o ) { return collection.contains( o ); }
|
|
+ public ObjectIterator <K> iterator() { return ObjectIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ public boolean add( final K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> unmodifiable( final ObjectCollection <K> c ) { return new UnmodifiableCollection <K>( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection <K> extends AbstractObjectCollection <K> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectIterable <K> iterable;
|
|
+ protected IterableCollection( final ObjectIterable <K> iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final ObjectIterator <K> iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public ObjectIterator <K> iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> asCollection( final ObjectIterable <K> iterable ) {
|
|
+ if ( iterable instanceof ObjectCollection ) return (ObjectCollection <K>)iterable;
|
|
+ return new IterableCollection <K>( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
|
|
new file mode 100644
|
|
index 0000000..5835740
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
|
|
@@ -0,0 +1,87 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “colon” <code>for</code> statements with primitive-type
|
|
+ * loop variables; however, what is (unfortunately) really happening is that at each iteration an
|
|
+ * unboxing (and, in the case of <code>fastutil</code> type-specific data structures, a boxing) will be performed. Watch out.
|
|
+ *
|
|
+ * @see Iterable
|
|
+ */
|
|
+public interface ObjectIterable <K> extends Iterable<K> {
|
|
+ /** Returns a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * @return a type-specific iterator.
|
|
+ */
|
|
+ ObjectIterator <K> iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
|
|
new file mode 100644
|
|
index 0000000..b3af95f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
|
|
@@ -0,0 +1,88 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface ObjectIterator <K> extends Iterator<K> {
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
|
|
new file mode 100644
|
|
index 0000000..f4c7afd
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
|
|
@@ -0,0 +1,558 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class ObjectIterators {
|
|
+ private ObjectIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator <K> extends AbstractObjectListIterator <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public K next() { throw new NoSuchElementException(); }
|
|
+ public K previous() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ private final K element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final K element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public K previous() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> singleton( final K element ) {
|
|
+ return new SingletonIterator <K>( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ private final K[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final K[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public K previous() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> wrap( final K[] array, final int offset, final int length ) {
|
|
+ ObjectArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator <K>( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> wrap( final K[] array ) {
|
|
+ return new ArrayIterator <K>( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.next();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> K[] unwrap( final Iterator <? extends K> i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ K array[] = (K[]) new Object[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = ObjectArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.next();
|
|
+ }
|
|
+ return ObjectArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static <K> K[] unwrap( final Iterator <? extends K> i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <K> i, final ObjectCollection <? super K> c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.next() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> long unwrap( final Iterator <K> i, final ObjectCollection <? super K> c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.next() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.next() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static <K> ObjectList <K> pour( final Iterator <K> i, int max ) {
|
|
+ final ObjectArrayList <K> l = new ObjectArrayList <K>();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static <K> ObjectList <K> pour( final Iterator <K> i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper <K> extends AbstractObjectIterator <K> {
|
|
+ final Iterator<K> i;
|
|
+ public IteratorWrapper( final Iterator<K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public K next() { return (i.next()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> asObjectIterator( final Iterator <K> i ) {
|
|
+ if ( i instanceof ObjectIterator ) return (ObjectIterator <K>)i;
|
|
+ return new IteratorWrapper <K>( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper <K> extends AbstractObjectListIterator <K> {
|
|
+ final ListIterator<K> i;
|
|
+ public ListIteratorWrapper( final ListIterator<K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( K k ) { i.set( (k) ); }
|
|
+ public void add( K k ) { i.add( (k) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public K next() { return (i.next()); }
|
|
+ public K previous() { return (i.previous()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> asObjectIterator( final ListIterator <K> i ) {
|
|
+ if ( i instanceof ObjectListIterator ) return (ObjectListIterator <K>)i;
|
|
+ return new ListIteratorWrapper <K>( i );
|
|
+ }
|
|
+ private static class IteratorConcatenator <K> extends AbstractObjectIterator <K> {
|
|
+ final ObjectIterator <? extends K> a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final ObjectIterator <? extends K> a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ K next = a[ lastOffset = offset ].next();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator <K>( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator <K> extends AbstractObjectIterator <K> {
|
|
+ final protected ObjectIterator <K> i;
|
|
+ public UnmodifiableIterator( final ObjectIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public K next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> unmodifiable( final ObjectIterator <K> i ) { return new UnmodifiableIterator <K>( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator <K> extends AbstractObjectBidirectionalIterator <K> {
|
|
+ final protected ObjectBidirectionalIterator <K> i;
|
|
+ public UnmodifiableBidirectionalIterator( final ObjectBidirectionalIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public K next() { return i.next(); }
|
|
+ public K previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static <K> ObjectBidirectionalIterator <K> unmodifiable( final ObjectBidirectionalIterator <K> i ) { return new UnmodifiableBidirectionalIterator <K>( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ final protected ObjectListIterator <K> i;
|
|
+ public UnmodifiableListIterator( final ObjectListIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public K next() { return i.next(); }
|
|
+ public K previous() { return i.previous(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> unmodifiable( final ObjectListIterator <K> i ) { return new UnmodifiableListIterator <K>( i ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
|
|
new file mode 100644
|
|
index 0000000..7b376b7
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
|
|
@@ -0,0 +1,169 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface ObjectList <K> extends List<K>, Comparable<List<? extends K>>, ObjectCollection <K> {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ ObjectListIterator <K> iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectListIterator <K> objectListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectListIterator <K> objectListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ ObjectListIterator <K> listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ ObjectListIterator <K> listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectList <K> objectSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ ObjectList <K> subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, Object a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, K a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, K a[], int offset, int length );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
|
|
new file mode 100644
|
|
index 0000000..f7f0b36
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
|
|
@@ -0,0 +1,82 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface ObjectListIterator <K> extends ListIterator<K>, ObjectBidirectionalIterator <K> {
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
|
|
new file mode 100644
|
|
index 0000000..02fa79f
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
|
|
@@ -0,0 +1,96 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface ObjectSet <K> extends ObjectCollection <K>, Set<K> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ ObjectIterator <K> iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( Object k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
|
|
new file mode 100644
|
|
index 0000000..63e5049
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
|
|
@@ -0,0 +1,177 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectSets {
|
|
+ private ObjectSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet <K> extends ObjectCollections.EmptyCollection <K> implements ObjectSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** Return an empty set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
|
|
+ * @return an empty set (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> ObjectSet <K> emptySet() {
|
|
+ return EMPTY_SET;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final K element;
|
|
+ protected Singleton( final K element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return ( (k) == null ? (element) == null : (k).equals(element) ); }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectListIterator <K> iterator() { return ObjectIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSet <K> singleton( final K element ) {
|
|
+ return new Singleton <K>( element );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet <K> extends ObjectCollections.SynchronizedCollection <K> implements ObjectSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final ObjectSet <K> s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final ObjectSet <K> s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final Object k ) { synchronized( sync ) { return collection.remove( (k) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s ) { return new SynchronizedSet <K>( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s, final Object sync ) { return new SynchronizedSet <K>( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet <K> extends ObjectCollections.UnmodifiableCollection <K> implements ObjectSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final ObjectSet <K> s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> unmodifiable( final ObjectSet <K> s ) { return new UnmodifiableSet <K>( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
|
|
new file mode 100644
|
|
index 0000000..d2777fb
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
|
|
@@ -0,0 +1,151 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface ObjectSortedSet <K> extends ObjectSet <K>, SortedSet<K> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ ObjectBidirectionalIterator <K> iterator( K fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectBidirectionalIterator <K> objectIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ ObjectBidirectionalIterator <K> iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> subSet( K fromElement, K toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> headSet( K toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> tailSet( K fromElement );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
|
|
new file mode 100644
|
|
index 0000000..b6142a0
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
|
|
@@ -0,0 +1,237 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+import java.util.Comparator;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectSortedSets {
|
|
+ private ObjectSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet <K> extends ObjectSets.EmptySet <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectBidirectionalIterator <K> iterator( K from ) { return ObjectIterators.EMPTY_ITERATOR; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> subSet( K from, K to ) { return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> headSet( K from ) { return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> tailSet( K to ) { return EMPTY_SET; }
|
|
+ public K first() { throw new NoSuchElementException(); }
|
|
+ public K last() { throw new NoSuchElementException(); }
|
|
+ public Comparator <? super K> comparator() { return null; }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** Return an empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
|
|
+ * @return an empty sorted set (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> ObjectSet <K> emptySet() {
|
|
+ return EMPTY_SET;
|
|
+ }
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton <K> extends ObjectSets.Singleton <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final Comparator <? super K> comparator;
|
|
+ private Singleton( final K element, final Comparator <? super K> comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final K element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ final int compare( final K k1, final K k2 ) {
|
|
+ return comparator == null ? ( ((Comparable<K>)(k1)).compareTo(k2) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator <K> iterator( K from ) {
|
|
+ ObjectBidirectionalIterator <K> i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { return comparator; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public K first() { return element; }
|
|
+ public K last() { return element; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> singleton( final K element ) {
|
|
+ return new Singleton <K>( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> singleton( final K element, final Comparator <? super K> comparator ) {
|
|
+ return new Singleton <K>( element, comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet <K> extends ObjectSets.SynchronizedSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectSortedSet <K> sortedSet;
|
|
+ protected SynchronizedSortedSet( final ObjectSortedSet <K> s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final ObjectSortedSet <K> s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { return new SynchronizedSortedSet <K>( sortedSet.subSet( from, to ), sync ); }
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { return new SynchronizedSortedSet <K>( sortedSet.headSet( to ), sync ); }
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { return new SynchronizedSortedSet <K>( sortedSet.tailSet( from ), sync ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return sortedSet.iterator(); }
|
|
+ public ObjectBidirectionalIterator <K> iterator( final K from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return sortedSet.iterator(); }
|
|
+ public K first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public K last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s ) { return new SynchronizedSortedSet <K>( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s, final Object sync ) { return new SynchronizedSortedSet <K>( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet <K> extends ObjectSets.UnmodifiableSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectSortedSet <K> sortedSet;
|
|
+ protected UnmodifiableSortedSet( final ObjectSortedSet <K> s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { return sortedSet.comparator(); }
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.subSet( from, to ) ); }
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.headSet( to ) ); }
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { return new UnmodifiableSortedSet <K>( sortedSet.tailSet( from ) ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator( final K from ) { return ObjectIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
|
|
+ public K first() { return sortedSet.first(); }
|
|
+ public K last() { return sortedSet.last(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> unmodifiable( final ObjectSortedSet <K> s ) { return new UnmodifiableSortedSet <K>( s ); }
|
|
+}
|
|
--
|
|
2.8.0
|
|
|