mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-01 17:01:56 +01:00
092dbc4bea
Importing the full library would double the jar size... its way too large. So lets just import the basic int/long based collections to then use to improve performance on these kind of collections.
45207 lines
No EOL
1.8 MiB
45207 lines
No EOL
1.8 MiB
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Mon, 21 Mar 2016 18:17:14 -0400
|
|
Subject: [PATCH] Add minimal fastutil int based collections
|
|
|
|
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectDoublePriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link IndirectDoublePriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #secondaryLast()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractIndirectDoublePriorityQueue<K> extends AbstractIndirectPriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
|
|
+
|
|
+ public int secondaryLast() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractIndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link IndirectPriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #changed(int)}, {@link #allChanged()}, {@link #remove(int)} and {@link #last()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
|
|
+
|
|
+ public int last() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public void changed() { changed( first() ); }
|
|
+
|
|
+ public void changed( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public void allChanged() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean remove( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean contains( int index ) { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean isEmpty() { return size() == 0; }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link PriorityQueue} interface.
|
|
+ *
|
|
+ * <P>This class defines {@link #changed()} and {@link #last()} as throwing an
|
|
+ * {@link UnsupportedOperationException}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractPriorityQueue<K> implements PriorityQueue<K> {
|
|
+
|
|
+ public void changed() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public K last() { throw new UnsupportedOperationException(); }
|
|
+
|
|
+ public boolean isEmpty() { return size() == 0; }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/AbstractStack.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** An abstract class providing basic methods for implementing the {@link Stack} interface.
|
|
+ *
|
|
+ * <P>This class just defines {@link Stack#top()} as {@link Stack#peek(int) peek(0)}, and
|
|
+ * {@link Stack#peek(int)} as throwing an {@link UnsupportedOperationException}.
|
|
+ *
|
|
+ * Subclasses of this class may choose to implement just {@link Stack#push(Object)},
|
|
+ * {@link Stack#pop()} and {@link Stack#isEmpty()}, or (but this is not
|
|
+ * required) go farther and implement {@link Stack#top()}, or even {@link
|
|
+ * Stack#peek(int)}.
|
|
+ */
|
|
+
|
|
+public abstract class AbstractStack<K> implements Stack<K> {
|
|
+
|
|
+ public K top() {
|
|
+ return peek( 0 );
|
|
+ }
|
|
+
|
|
+ public K peek( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Arrays.java b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Arrays.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import it.unimi.dsi.fastutil.ints.IntComparator;
|
|
+
|
|
+import java.util.ArrayList;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with arrays.
|
|
+ *
|
|
+ * <p>In addition to commodity methods, this class contains {@link Swapper}-based implementations
|
|
+ * of {@linkplain #quickSort(int, int, IntComparator, Swapper) quicksort} and of
|
|
+ * a stable, in-place {@linkplain #mergeSort(int, int, IntComparator, Swapper) mergesort}. These
|
|
+ * generic sorting methods can be used to sort any kind of list, but they find their natural
|
|
+ * usage, for instance, in sorting arrays in parallel.
|
|
+ *
|
|
+ * @see Arrays
|
|
+ */
|
|
+
|
|
+public class Arrays {
|
|
+
|
|
+ private Arrays() {}
|
|
+
|
|
+ /** This is a safe value used by {@link ArrayList} (as of Java 7) to avoid
|
|
+ * throwing {@link OutOfMemoryError} on some JVMs. We adopt the same value. */
|
|
+ public static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
|
|
+
|
|
+ /** Ensures that a range given by its first (inclusive) and last (exclusive) elements fits an array of given length.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param arrayLength an array length.
|
|
+ * @param from a start index (inclusive).
|
|
+ * @param to an end index (inclusive).
|
|
+ * @throws IllegalArgumentException if <code>from</code> is greater than <code>to</code>.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>from</code> or <code>to</code> are greater than <code>arrayLength</code> or negative.
|
|
+ */
|
|
+ public static void ensureFromTo( final int arrayLength, final int from, final int to ) {
|
|
+ if ( from < 0 ) throw new ArrayIndexOutOfBoundsException( "Start index (" + from + ") is negative" );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( to > arrayLength ) throw new ArrayIndexOutOfBoundsException( "End index (" + to + ") is greater than array length (" + arrayLength + ")" );
|
|
+ }
|
|
+
|
|
+ /** Ensures that a range given by an offset and a length fits an array of given length.
|
|
+ *
|
|
+ * <P>This method may be used whenever an array range check is needed.
|
|
+ *
|
|
+ * @param arrayLength an array length.
|
|
+ * @param offset a start index for the fragment
|
|
+ * @param length a length (the number of elements in the fragment).
|
|
+ * @throws IllegalArgumentException if <code>length</code> is negative.
|
|
+ * @throws ArrayIndexOutOfBoundsException if <code>offset</code> is negative or <code>offset</code>+<code>length</code> is greater than <code>arrayLength</code>.
|
|
+ */
|
|
+ public static void ensureOffsetLength( final int arrayLength, final int offset, final int length ) {
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( length < 0 ) throw new IllegalArgumentException( "Length (" + length + ") is negative" );
|
|
+ if ( offset + length > arrayLength ) throw new ArrayIndexOutOfBoundsException( "Last index (" + ( offset + length ) + ") is greater than array length (" + arrayLength + ")" );
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Transforms two consecutive sorted ranges into a single sorted range. The initial ranges are
|
|
+ * <code>[first..middle)</code> and <code>[middle..last)</code>, and the resulting range is
|
|
+ * <code>[first..last)</code>. Elements in the first input range will precede equal elements in
|
|
+ * the second.
|
|
+ */
|
|
+ private static void inPlaceMerge( final int from, int mid, final int to, final IntComparator comp, final Swapper swapper ) {
|
|
+ if ( from >= mid || mid >= to ) return;
|
|
+ if ( to - from == 2 ) {
|
|
+ if ( comp.compare( mid, from ) < 0 ) swapper.swap( from, mid );
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ int firstCut;
|
|
+ int secondCut;
|
|
+
|
|
+ if ( mid - from > to - mid ) {
|
|
+ firstCut = from + ( mid - from ) / 2;
|
|
+ secondCut = lowerBound( mid, to, firstCut, comp );
|
|
+ }
|
|
+ else {
|
|
+ secondCut = mid + ( to - mid ) / 2;
|
|
+ firstCut = upperBound( from, mid, secondCut, comp );
|
|
+ }
|
|
+
|
|
+ int first2 = firstCut;
|
|
+ int middle2 = mid;
|
|
+ int last2 = secondCut;
|
|
+ if ( middle2 != first2 && middle2 != last2 ) {
|
|
+ int first1 = first2;
|
|
+ int last1 = middle2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ first1 = middle2;
|
|
+ last1 = last2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ first1 = first2;
|
|
+ last1 = last2;
|
|
+ while ( first1 < --last1 )
|
|
+ swapper.swap( first1++, last1 );
|
|
+ }
|
|
+
|
|
+ mid = firstCut + ( secondCut - mid );
|
|
+ inPlaceMerge( from, firstCut, mid, comp, swapper );
|
|
+ inPlaceMerge( mid, secondCut, to, comp, swapper );
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Performs a binary search on an already-sorted range: finds the first position where an
|
|
+ * element can be inserted without violating the ordering. Sorting is by a user-supplied
|
|
+ * comparison function.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be included in the binary search.
|
|
+ * @param to the index of the last element (exclusive) to be included in the binary search.
|
|
+ * @param pos the position of the element to be searched for.
|
|
+ * @param comp the comparison function.
|
|
+ * @return the largest index i such that, for every j in the range <code>[first..i)</code>,
|
|
+ * <code>comp.compare(j, pos)</code> is <code>true</code>.
|
|
+ */
|
|
+ private static int lowerBound( int from, final int to, final int pos, final IntComparator comp ) {
|
|
+ // if (comp==null) throw new NullPointerException();
|
|
+ int len = to - from;
|
|
+ while ( len > 0 ) {
|
|
+ int half = len / 2;
|
|
+ int middle = from + half;
|
|
+ if ( comp.compare( middle, pos ) < 0 ) {
|
|
+ from = middle + 1;
|
|
+ len -= half + 1;
|
|
+ }
|
|
+ else {
|
|
+ len = half;
|
|
+ }
|
|
+ }
|
|
+ return from;
|
|
+ }
|
|
+
|
|
+
|
|
+ /**
|
|
+ * Performs a binary search on an already sorted range: finds the last position where an element
|
|
+ * can be inserted without violating the ordering. Sorting is by a user-supplied comparison
|
|
+ * function.
|
|
+ *
|
|
+ * @param from the index of the first element (inclusive) to be included in the binary search.
|
|
+ * @param to the index of the last element (exclusive) to be included in the binary search.
|
|
+ * @param pos the position of the element to be searched for.
|
|
+ * @param comp the comparison function.
|
|
+ * @return The largest index i such that, for every j in the range <code>[first..i)</code>,
|
|
+ * <code>comp.compare(pos, j)</code> is <code>false</code>.
|
|
+ */
|
|
+ private static int upperBound( int from, final int mid, final int pos, final IntComparator comp ) {
|
|
+ // if (comp==null) throw new NullPointerException();
|
|
+ int len = mid - from;
|
|
+ while ( len > 0 ) {
|
|
+ int half = len / 2;
|
|
+ int middle = from + half;
|
|
+ if ( comp.compare( pos, middle ) < 0 ) {
|
|
+ len = half;
|
|
+ }
|
|
+ else {
|
|
+ from = middle + 1;
|
|
+ len -= half + 1;
|
|
+ }
|
|
+ }
|
|
+ return from;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the index of the median of the three indexed chars.
|
|
+ */
|
|
+ private static int med3( final int a, final int b, final int c, final IntComparator comp ) {
|
|
+ int ab = comp.compare( a, b );
|
|
+ int ac = comp.compare( a, c );
|
|
+ int bc = comp.compare( b, c );
|
|
+ return ( ab < 0 ?
|
|
+ ( bc < 0 ? b : ac < 0 ? c : a ) :
|
|
+ ( bc > 0 ? b : ac > 0 ? c : a ) );
|
|
+ }
|
|
+
|
|
+ private static final int MERGESORT_NO_REC = 16;
|
|
+
|
|
+ /** Sorts the specified range of elements using the specified swapper and according to the order induced by the specified
|
|
+ * comparator using mergesort.
|
|
+ *
|
|
+ * <p>This sort is guaranteed to be <i>stable</i>: equal elements will not be reordered as a result
|
|
+ * of the sort. The sorting algorithm is an in-place mergesort that is significantly slower than a
|
|
+ * standard mergesort, as its running time is <i>O</i>(<var>n</var> (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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/BidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+
|
|
+/** A bidirectional {@link Iterator}.
|
|
+ *
|
|
+ * <P>This kind of iterator is essentially a {@link ListIterator} that
|
|
+ * does not support {@link ListIterator#previousIndex()} and {@link
|
|
+ * ListIterator#nextIndex()}. It is useful for those maps that can easily
|
|
+ * provide bidirectional iteration, but provide no index.
|
|
+ *
|
|
+ * <P>Note that iterators returned by <code>fastutil</code> classes are more
|
|
+ * specific, and support skipping. This class serves the purpose of organising
|
|
+ * in a cleaner way the relationships between various iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ * @see ListIterator
|
|
+ */
|
|
+
|
|
+public interface BidirectionalIterator<K> extends Iterator<K> {
|
|
+
|
|
+ /** Returns the previous element from the collection.
|
|
+ *
|
|
+ * @return the previous element from the collection.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+
|
|
+ K previous();
|
|
+
|
|
+ /** Returns whether there is a previous element.
|
|
+ *
|
|
+ * @return whether there is a previous element.
|
|
+ * @see java.util.ListIterator#hasPrevious()
|
|
+ */
|
|
+
|
|
+ boolean hasPrevious();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/BigSwapper.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** An object that can swap elements whose positions is specified by longs.
|
|
+ *
|
|
+ * @see BigArrays#quickSort(long, long, it.unimi.dsi.fastutil.longs.LongComparator, BigSwapper)
|
|
+ */
|
|
+
|
|
+public interface BigSwapper {
|
|
+ /** Swaps the data at the given positions.
|
|
+ *
|
|
+ * @param a the first position to swap.
|
|
+ * @param b the second position to swap.
|
|
+ */
|
|
+ void swap( long a, long b );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Function.java b/src/main/java/it/unimi/dsi/fastutil/Function.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Function.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** A function mapping keys into values.
|
|
+ *
|
|
+ * <p>Instances of this class represent functions: the main difference with {@link java.util.Map}
|
|
+ * is that functions do not in principle allow enumeration of their domain or range. The need for
|
|
+ * this interface lies in the existence of several highly optimized implementations of
|
|
+ * functions (e.g., minimal perfect hashes) which do not actually store their domain or range explicitly.
|
|
+ * In case the domain is known, {@link #containsKey(Object)} can be used to perform membership queries.
|
|
+ *
|
|
+ * <p>The choice of naming all methods exactly as in {@link java.util.Map} makes it possible
|
|
+ * for all type-specific maps to extend type-specific functions (e.g., {@link it.unimi.dsi.fastutil.ints.Int2IntMap}
|
|
+ * extends {@link it.unimi.dsi.fastutil.ints.Int2IntFunction}). However, {@link #size()} is allowed to return -1 to denote
|
|
+ * that the number of keys is not available (e.g., in the case of a string hash function).
|
|
+ *
|
|
+ * <p>Note that there is an {@link it.unimi.dsi.fastutil.objects.Object2ObjectFunction} that
|
|
+ * can also set its default return value.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Equality of functions is <em>not specified</em>
|
|
+ * by contract, and it will usually be <em>by reference</em>, as there is no way to enumerate the keys
|
|
+ * and establish whether two functions represent the same mathematical entity.
|
|
+ *
|
|
+ * @see java.util.Map
|
|
+ */
|
|
+
|
|
+public interface Function<K,V> {
|
|
+
|
|
+ /** Associates the specified value with the specified key in this function (optional operation).
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#put(Object,Object)
|
|
+ */
|
|
+
|
|
+ V put( K key, V value );
|
|
+
|
|
+ /** Returns the value associated by this function to the specified key.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#get(Object)
|
|
+ */
|
|
+
|
|
+ V get( Object key );
|
|
+
|
|
+ /** Returns true if this function contains a mapping for the specified key.
|
|
+ *
|
|
+ * <p>Note that for some kind of functions (e.g., hashes) this method
|
|
+ * will always return true.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return true if this function associates a value to <code>key</code>.
|
|
+ * @see java.util.Map#containsKey(Object)
|
|
+ */
|
|
+
|
|
+ boolean containsKey( Object key );
|
|
+
|
|
+ /** Removes this key and the associated value from this function if it is present (optional operation).
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the old value, or <code>null</code> if no value was present for the given key.
|
|
+ * @see java.util.Map#remove(Object)
|
|
+ */
|
|
+
|
|
+ V remove( Object key );
|
|
+
|
|
+ /** Returns the intended number of keys in this function, or -1 if no such number exists.
|
|
+ *
|
|
+ * <p>Most function implementations will have some knowledge of the intended number of keys
|
|
+ * in their domain. In some cases, however, this might not be possible.
|
|
+ *
|
|
+ * @return the intended number of keys in this function, or -1 if that number is not available.
|
|
+ */
|
|
+ int size();
|
|
+
|
|
+ /** Removes all associations from this function (optional operation).
|
|
+ *
|
|
+ * @see java.util.Map#clear()
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Hash.java b/src/main/java/it/unimi/dsi/fastutil/Hash.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Hash.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** Basic data for all hash-based classes.
|
|
+ *
|
|
+ * <h2>Historical note</h2>
|
|
+ *
|
|
+ * <p><strong>Warning:</strong> the following comments are here for historical reasons,
|
|
+ * and apply just to the <em>double hash</em> classes that can be optionally generated.
|
|
+ * The standard <code>fastutil</code> distribution since 6.1.0 uses linear-probing hash
|
|
+ * tables, and tables are always sized as powers of two.
|
|
+ *
|
|
+ * <p>The classes in <code>fastutil</code> are built around open-addressing hashing
|
|
+ * implemented <em>via</em> double hashing. Following Knuth's suggestions in the third volume of <em>The Art of Computer
|
|
+ * Programming</em>, we use for the table size a prime <var>p</var> such that
|
|
+ * <var>p</var>-2 is also prime. In this way hashing is implemented with modulo <var>p</var>,
|
|
+ * and secondary hashing with modulo <var>p</var>-2.
|
|
+ *
|
|
+ * <p>Entries in a table can be in three states: {@link #FREE}, {@link #OCCUPIED} or {@link #REMOVED}.
|
|
+ * The naive handling of removed entries requires that you search for a free entry as if they were occupied. However,
|
|
+ * <code>fastutil</code> implements two useful optimizations, based on the following invariant:
|
|
+ * <blockquote>
|
|
+ * Let <var>i</var><sub>0</sub>, <var>i</var><sub>1</sub>, …, <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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/HashCommon.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** Common code for all hash-based classes. */
|
|
+
|
|
+public class HashCommon {
|
|
+
|
|
+ protected HashCommon() {};
|
|
+
|
|
+ /** This reference is used to fill keys and values of removed entries (if
|
|
+ they are objects). <code>null</code> cannot be used as it would confuse the
|
|
+ search algorithm in the presence of an actual <code>null</code> key. */
|
|
+ public static final Object REMOVED = new Object();
|
|
+
|
|
+ /** 2<sup>32</sup> · φ, φ = (√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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+
|
|
+/** An indirect double priority queue.
|
|
+ *
|
|
+ * <P>An indirect double priority queue uses two distinct comparators (called <em>primary</em>
|
|
+ * and <em>secondary</em>) to keep its elements ordered. It makes it possible to access the
|
|
+ * first element w.r.t. the secondary comparatory using {@link #secondaryFirst()} (and, optionally,
|
|
+ * the last element using {@link #secondaryLast()}). The remaining methods
|
|
+ * work like those of an {@linkplain it.unimi.dsi.fastutil.IndirectPriorityQueue indirect priority queue} based on the
|
|
+ * primary comparator.
|
|
+ */
|
|
+
|
|
+public interface IndirectDoublePriorityQueue<K> extends IndirectPriorityQueue<K> {
|
|
+
|
|
+ /** Returns the secondary comparator of this queue.
|
|
+ *
|
|
+ * @return the secondary comparator of this queue.
|
|
+ * @see #secondaryFirst()
|
|
+ */
|
|
+ public Comparator<? super K> secondaryComparator();
|
|
+
|
|
+ /** Returns the first element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ *
|
|
+ * @return the first element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ */
|
|
+ public int secondaryFirst();
|
|
+
|
|
+ /** Returns the last element of this queue with respect to the {@linkplain #secondaryComparator() secondary comparator} (optional operation).
|
|
+ *
|
|
+ * @return the last element of this queue w.r.t. the {@linkplain #secondaryComparator() secondary comparator}.
|
|
+ */
|
|
+ public int secondaryLast();
|
|
+
|
|
+ /** Retrieves the secondary front of the queue in a given array (optional operation).
|
|
+ *
|
|
+ * @param a an array large enough to hold the secondary front (e.g., at least long as the reference array).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ * @see IndirectPriorityQueue#front(int[])
|
|
+ */
|
|
+
|
|
+ public int secondaryFront( final int[] a );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectDoublePriorityQueues.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with indirect priority queues.
|
|
+ *
|
|
+ * @see IndirectDoublePriorityQueue
|
|
+ */
|
|
+
|
|
+public class IndirectDoublePriorityQueues {
|
|
+
|
|
+ private IndirectDoublePriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty indirect double priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link IndirectDoublePriorityQueue}.
|
|
+ */
|
|
+
|
|
+ public static class EmptyIndirectDoublePriorityQueue extends IndirectPriorityQueues.EmptyIndirectPriorityQueue {
|
|
+
|
|
+ protected EmptyIndirectDoublePriorityQueue() {}
|
|
+
|
|
+ public int secondaryFirst() { throw new NoSuchElementException(); }
|
|
+ public int secondaryLast() { throw new NoSuchElementException(); }
|
|
+ public Comparator<?> secondaryComparator() { return null; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect double priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyIndirectDoublePriorityQueue EMPTY_QUEUE = new EmptyIndirectDoublePriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for indirect double priority queues. */
|
|
+
|
|
+ public static class SynchronizedIndirectDoublePriorityQueue<K> implements IndirectDoublePriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected IndirectDoublePriorityQueue<K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedIndirectDoublePriorityQueue( final IndirectDoublePriorityQueue<K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( int index ) { synchronized( sync ) { q.enqueue( index ); } }
|
|
+ public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public int first() { synchronized( sync ) { return q.first(); } }
|
|
+ public int last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
|
|
+ public int secondaryFirst() { synchronized( sync ) { return q.secondaryFirst(); } }
|
|
+ public int secondaryLast() { synchronized( sync ) { return q.secondaryLast(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public void allChanged() { synchronized( sync ) { q.allChanged(); } }
|
|
+ public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
|
|
+ public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
|
|
+ public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public Comparator<? super K> secondaryComparator() { synchronized( sync ) { return q.secondaryComparator(); } }
|
|
+ public int secondaryFront( int[] a ) { return q.secondaryFront( a ); }
|
|
+ public int front( int[] a ) { return q.front( a ); }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue.
|
|
+ *
|
|
+ * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
|
|
+ * @return a synchronized view of the specified indirect double priority queue.
|
|
+ */
|
|
+ public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q ) { return new SynchronizedIndirectDoublePriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect double priority queue backed by the specified type-specific indirect double priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the indirect double priority queue to be wrapped in a synchronized indirect double priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the indirect double priority queue.
|
|
+ * @return a synchronized view of the specified indirect double priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> IndirectDoublePriorityQueue<K> synchronize( final IndirectDoublePriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectDoublePriorityQueue<K>( q, sync ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** An indirect priority queue.
|
|
+ *
|
|
+ * <P>An indirect priority queue provides a way to {@linkplain #enqueue(int)
|
|
+ * enqueue} by index elements taken from a given <em>reference list</em>,
|
|
+ * and to {@linkplain #dequeue() dequeue} them in some specified order.
|
|
+ * Elements that are <em>smaller</em> in the specified order are
|
|
+ * dequeued first. It
|
|
+ * is also possible to get the {@linkplain #first() index of the first element}, that
|
|
+ * is, the index that would be dequeued next.
|
|
+ *
|
|
+ * <P>Additionally, the queue may provide a method to peek at the index of the
|
|
+ * element that would be dequeued {@linkplain #last() last}.
|
|
+ *
|
|
+ * <P>The reference list should not change during queue operations (or, more
|
|
+ * precisely, the relative order of the elements corresponding to indices in the queue should not
|
|
+ * change). Nonetheless, some implementations may give the caller a way to
|
|
+ * notify the queue that the {@linkplain #changed() first element has changed its
|
|
+ * relative position in the order}.
|
|
+ *
|
|
+ * <P>Optionally, an indirect priority queue may even provide methods to notify
|
|
+ * {@linkplain #changed(int) the change of <em>any</em> element of the
|
|
+ * reference list}, to check {@linkplain #contains(int) the presence of
|
|
+ * an index in the queue}, and to {@linkplain #remove(int) remove an index from the queue}.
|
|
+ * It may even allow to notify that {@linkplain #allChanged() all elements have changed}.
|
|
+ *
|
|
+ * <P>It is always possible to enqueue two distinct indices corresponding to
|
|
+ * equal elements of the reference list. However, depending on the
|
|
+ * implementation, it may or may not be possible to enqueue twice the same
|
|
+ * index.
|
|
+ *
|
|
+ * <P>Note that <em>all element manipulation happens via indices</em>.
|
|
+ */
|
|
+
|
|
+public interface IndirectPriorityQueue<K> {
|
|
+
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param index the element to enqueue.
|
|
+ */
|
|
+
|
|
+ void enqueue( int index );
|
|
+
|
|
+ /** Dequeues the {@linkplain #first() first} element from this queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int dequeue();
|
|
+
|
|
+ /** Checks whether this queue is empty.
|
|
+ *
|
|
+ * @return true if this queue is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Returns the number of elements in this queue.
|
|
+ *
|
|
+ * @return the number of elements in this queue.
|
|
+ */
|
|
+
|
|
+ int size();
|
|
+
|
|
+ /** Removes all elements from this queue.
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+ /** Returns the first element of this queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int first();
|
|
+
|
|
+ /** Returns the last element of this queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if this queue is empty.
|
|
+ */
|
|
+
|
|
+ int last();
|
|
+
|
|
+ /** Notifies this queue that the {@linkplain #first() first element} has changed (optional operation).
|
|
+ *
|
|
+ */
|
|
+
|
|
+ void changed();
|
|
+
|
|
+ /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ */
|
|
+ Comparator <? super K> comparator();
|
|
+
|
|
+ /** Notifies this queue that the specified element has changed (optional operation).
|
|
+ *
|
|
+ * <P>Note that the specified element must belong to this queue.
|
|
+ *
|
|
+ * @param index the element that has changed.
|
|
+ * @throws NoSuchElementException if the specified element is not in this queue.
|
|
+ */
|
|
+
|
|
+ public void changed( int index );
|
|
+
|
|
+ /** Notifies this queue that the all elements have changed (optional operation).
|
|
+ */
|
|
+
|
|
+ public void allChanged();
|
|
+
|
|
+ /** Checks whether a given index belongs to this queue (optional operation).
|
|
+ *
|
|
+ * @param index an index possibly in the queue.
|
|
+ * @return true if the specified index belongs to this queue.
|
|
+ */
|
|
+ public boolean contains( int index );
|
|
+
|
|
+ /** Removes the specified element from this queue (optional operation).
|
|
+ *
|
|
+ * @param index the element to be removed.
|
|
+ * @return true if the index was in the queue.
|
|
+ */
|
|
+
|
|
+ public boolean remove( int index );
|
|
+
|
|
+ /** Retrieves the front of this queue in a given array (optional operation).
|
|
+ *
|
|
+ * <p>The <em>front</em> of an indirect queue is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the {@linkplain #first() first index}. These indices can be always obtain by dequeueing, but
|
|
+ * this method should retrieve efficiently such indices in the given array without modifying the state of this queue.
|
|
+ *
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as the reference array).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+
|
|
+ public int front( final int[] a );
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/IndirectPriorityQueues.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with indirect priority queues.
|
|
+ *
|
|
+ * @see IndirectPriorityQueue
|
|
+ */
|
|
+
|
|
+public class IndirectPriorityQueues {
|
|
+
|
|
+ private IndirectPriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty indirect priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link IndirectPriorityQueue}.
|
|
+ */
|
|
+
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static class EmptyIndirectPriorityQueue extends AbstractIndirectPriorityQueue {
|
|
+
|
|
+ protected EmptyIndirectPriorityQueue() {}
|
|
+
|
|
+ public void enqueue( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int dequeue() { throw new NoSuchElementException(); }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ public int size() { return 0; }
|
|
+ public boolean contains( int index ) { return false; }
|
|
+ public void clear() {}
|
|
+ public int first() { throw new NoSuchElementException(); }
|
|
+ public int last() { throw new NoSuchElementException(); }
|
|
+ public void changed() { throw new NoSuchElementException(); }
|
|
+ public void allChanged() {}
|
|
+ public Comparator<?> comparator() { return null; }
|
|
+ public void changed( final int i ) { throw new IllegalArgumentException( "Index " + i + " is not in the queue" ); }
|
|
+ public boolean remove( final int i ) { return false; }
|
|
+ public int front( int[] a ) { return 0; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyIndirectPriorityQueue EMPTY_QUEUE = new EmptyIndirectPriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for indirect priority queues. */
|
|
+
|
|
+ public static class SynchronizedIndirectPriorityQueue<K> implements IndirectPriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected IndirectPriorityQueue<K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedIndirectPriorityQueue( final IndirectPriorityQueue<K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public int dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public boolean contains( final int index ) { synchronized( sync ) { return q.contains( index ); } }
|
|
+ public int first() { synchronized( sync ) { return q.first(); } }
|
|
+ public int last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public void allChanged() { synchronized( sync ) { q.allChanged(); } }
|
|
+ public void changed( int i ) { synchronized( sync ) { q.changed( i ); } }
|
|
+ public boolean remove( int i ) { synchronized( sync ) { return q.remove( i ); } }
|
|
+ public Comparator<? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public int front( int[] a ) { return q.front( a ); }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue.
|
|
+ *
|
|
+ * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
|
|
+ * @return a synchronized view of the specified indirect priority queue.
|
|
+ */
|
|
+ public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q ) { return new SynchronizedIndirectPriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized type-specific indirect priority queue backed by the specified type-specific indirect priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the indirect priority queue to be wrapped in a synchronized indirect priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the indirect priority queue.
|
|
+ * @return a synchronized view of the specified indirect priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> IndirectPriorityQueue<K> synchronize( final IndirectPriorityQueue<K> q, final Object sync ) { return new SynchronizedIndirectPriorityQueue<K>( q, sync ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Maps.java b/src/main/java/it/unimi/dsi/fastutil/Maps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Maps.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+
|
|
+public class Maps {
|
|
+
|
|
+ private Maps() {}
|
|
+
|
|
+ /** A standard default return value to be used in maps containing <code>null</code> values.
|
|
+ * @deprecated Since fastutil 5.0, the introduction of generics
|
|
+ * makes this object pretty useless.
|
|
+ */
|
|
+
|
|
+ @Deprecated
|
|
+ public static final Object MISSING = new Object();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A priority queue.
|
|
+ *
|
|
+ * <P>A priority queue provides a way to {@linkplain #enqueue(Object) enqueue}
|
|
+ * elements, and to {@linkplain #dequeue() dequeue} them in some specified
|
|
+ * order. Elements that are <em>smaller</em> in the specified order are
|
|
+ * dequeued first. It is also possible to get the {@linkplain #first() first
|
|
+ * element}, that is, the element that would be dequeued next.
|
|
+ *
|
|
+ * <P>Additionally, the queue may provide a method to peek at
|
|
+ * element that would be dequeued {@linkplain #last() last}.
|
|
+ *
|
|
+ * <P>The relative order of the elements enqueued should not change during
|
|
+ * queue operations. Nonetheless, some implementations may give the caller a
|
|
+ * way to notify the queue that the {@linkplain #changed() first element has
|
|
+ * changed its relative position in the order}.
|
|
+ */
|
|
+
|
|
+public interface PriorityQueue<K> {
|
|
+
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue..
|
|
+ */
|
|
+
|
|
+ void enqueue( K x );
|
|
+
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K dequeue();
|
|
+
|
|
+ /** Checks whether the queue is empty.
|
|
+ *
|
|
+ * @return true if the queue is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Returns the number of elements in this queue.
|
|
+ *
|
|
+ * @return the number of elements in this queue.
|
|
+ */
|
|
+
|
|
+ int size();
|
|
+
|
|
+ /** Removes all elements from this queue.
|
|
+ */
|
|
+
|
|
+ void clear();
|
|
+
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K first();
|
|
+
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+
|
|
+ K last();
|
|
+
|
|
+ /** Notifies the queue that the {@linkplain #first() first} element has changed (optional operation).
|
|
+ */
|
|
+
|
|
+ void changed();
|
|
+
|
|
+ /** Returns the comparator associated with this queue, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * @return the comparator associated with this sorted set, or <code>null</code> if it uses its elements' natural ordering.
|
|
+ */
|
|
+ Comparator<? super K> comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/PriorityQueues.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.Comparator;
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+
|
|
+/** A class providing static methods and objects that do useful things with priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+
|
|
+public class PriorityQueues {
|
|
+
|
|
+ private PriorityQueues() {}
|
|
+
|
|
+ /** An immutable class representing the empty priority queue.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * {@link PriorityQueue}.
|
|
+ */
|
|
+
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static class EmptyPriorityQueue extends AbstractPriorityQueue {
|
|
+
|
|
+ protected EmptyPriorityQueue() {}
|
|
+
|
|
+ public void enqueue( Object o ) { throw new UnsupportedOperationException(); }
|
|
+ public Object dequeue() { throw new NoSuchElementException(); }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public Object first() { throw new NoSuchElementException(); }
|
|
+ public Object last() { throw new NoSuchElementException(); }
|
|
+ public void changed() { throw new NoSuchElementException(); }
|
|
+ public Comparator<?> comparator() { return null; }
|
|
+
|
|
+ }
|
|
+
|
|
+ /** An empty indirect priority queue (immutable).
|
|
+ */
|
|
+
|
|
+ public final static EmptyPriorityQueue EMPTY_QUEUE = new EmptyPriorityQueue();
|
|
+
|
|
+
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+
|
|
+ public static class SynchronizedPriorityQueue<K> implements PriorityQueue<K> {
|
|
+
|
|
+ public static final long serialVersionUID = -7046029254386353129L;
|
|
+
|
|
+ final protected PriorityQueue <K> q;
|
|
+ final protected Object sync;
|
|
+
|
|
+ protected SynchronizedPriorityQueue( final PriorityQueue <K> q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+
|
|
+ protected SynchronizedPriorityQueue( final PriorityQueue <K> q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+
|
|
+ public void enqueue( K x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public K dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public K first() { synchronized( sync ) { return q.first(); } }
|
|
+ public K last() { synchronized( sync ) { return q.last(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public Comparator <? super K> comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ }
|
|
+
|
|
+
|
|
+ /** Returns a synchronized priority queue backed by the specified priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q ) { return new SynchronizedPriorityQueue<K>( q ); }
|
|
+
|
|
+ /** Returns a synchronized priority queue backed by the specified priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+
|
|
+ public static <K> PriorityQueue <K> synchronize( final PriorityQueue <K> q, final Object sync ) { return new SynchronizedPriorityQueue<K>( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Size64.java b/src/main/java/it/unimi/dsi/fastutil/Size64.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Size64.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+import java.util.Collection;
|
|
+
|
|
+/** An interface for data structures whose size can exceed {@link Integer#MAX_VALUE}.
|
|
+ *
|
|
+ * <P>The only methods specified by this interfaces are {@link #size64()}, and
|
|
+ * a deprecated {@link #size()} identical to {@link Collection#size()}. Implementations
|
|
+ * can work around the type problem of {@link java.util.Collection#size()}
|
|
+ * (e.g., not being able to return more than {@link Integer#MAX_VALUE}) by implementing this
|
|
+ * interface. Callers interested in large structures
|
|
+ * can use a reflective call to <code>instanceof</code> to check for the presence of {@link #size64()}.
|
|
+ *
|
|
+ * <p>We remark that it is always a good idea to implement both {@link #size()} <em>and</em> {@link #size64()},
|
|
+ * as the former might be implemented by a superclass in an incompatible way. If you implement this interface,
|
|
+ * just implement {@link #size()} as a <em>deprecated</em> method returning <code>Math.min(Integer.MAX_VALUE, size64())</code>.
|
|
+ */
|
|
+
|
|
+public interface Size64 {
|
|
+ /** Returns the size of this data structure as a long.
|
|
+ *
|
|
+ * @return the size of this data structure.
|
|
+ */
|
|
+ long size64();
|
|
+
|
|
+ /** Returns the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
|
|
+ *
|
|
+ * @return the size of this data structure, minimized with {@link Integer#MAX_VALUE}.
|
|
+ * @see java.util.Collection#size()
|
|
+ * @deprecated Use {@link #size64()} instead.
|
|
+ */
|
|
+ @Deprecated
|
|
+ int size();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Stack.java b/src/main/java/it/unimi/dsi/fastutil/Stack.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Stack.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+
|
|
+import java.util.NoSuchElementException;
|
|
+
|
|
+/** A stack.
|
|
+ *
|
|
+ * <P>A stack must provide the classical {@link #push(Object)} and
|
|
+ * {@link #pop()} operations, but may be also <em>peekable</em>
|
|
+ * to some extent: it may provide just the {@link #top()} function,
|
|
+ * or even a more powerful {@link #peek(int)} method that provides
|
|
+ * access to all elements on the stack (indexed from the top, which
|
|
+ * has index 0).
|
|
+ */
|
|
+
|
|
+public interface Stack<K> {
|
|
+
|
|
+ /** Pushes the given object on the stack.
|
|
+ *
|
|
+ * @param o the object that will become the new top of the stack.
|
|
+ */
|
|
+
|
|
+ void push( K o );
|
|
+
|
|
+ /** Pops the top off the stack.
|
|
+ *
|
|
+ * @return the top of the stack.
|
|
+ * @throws NoSuchElementException if the stack is empty.
|
|
+ */
|
|
+
|
|
+ K pop();
|
|
+
|
|
+ /** Checks whether the stack is empty.
|
|
+ *
|
|
+ * @return true if the stack is empty.
|
|
+ */
|
|
+
|
|
+ boolean isEmpty();
|
|
+
|
|
+ /** Peeks at the top of the stack (optional operation).
|
|
+ *
|
|
+ * @return the top of the stack.
|
|
+ * @throws NoSuchElementException if the stack is empty.
|
|
+ */
|
|
+
|
|
+ K top();
|
|
+
|
|
+ /** Peeks at an element on the stack (optional operation).
|
|
+ *
|
|
+ * @param i an index from the stop of the stack (0 represents the top).
|
|
+ * @return the <code>i</code>-th element on the stack.
|
|
+ * @throws IndexOutOfBoundsException if the designated element does not exist..
|
|
+ */
|
|
+
|
|
+ K peek( int i );
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/Swapper.java b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/Swapper.java
|
|
@@ -0,0 +0,0 @@
|
|
+package it.unimi.dsi.fastutil;
|
|
+
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+
|
|
+/** An object that can swap elements whose position is specified by integers
|
|
+ *
|
|
+ * @see Arrays#quickSort(int, int, it.unimi.dsi.fastutil.ints.IntComparator, Swapper)
|
|
+ */
|
|
+
|
|
+public interface Swapper {
|
|
+ /** Swaps the data at the given positions.
|
|
+ *
|
|
+ * @param a the first position to swap.
|
|
+ * @param b the second position to swap.
|
|
+ */
|
|
+ void swap( int a, int b );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectFunction.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class providing basic methods for functions implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>This class handles directly a default return
|
|
+ * value (including {@linkplain #defaultReturnValue() methods to access
|
|
+ * it}). Instances of classes inheriting from this class have just to return
|
|
+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
|
|
+ * is serialized.
|
|
+ *
|
|
+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
|
|
+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractInt2ObjectFunction <V> implements Int2ObjectFunction <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractInt2ObjectFunction() {}
|
|
+ /**
|
|
+ * The default return value for <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code>.
|
|
+ */
|
|
+ protected V defRetValue;
|
|
+ public void defaultReturnValue( final V rv ) {
|
|
+ defRetValue = rv;
|
|
+ }
|
|
+ public V defaultReturnValue() {
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public V put( int key, V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public V remove( int key ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public void clear() {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean containsKey( final Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return containsKey( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V get( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ return containsKey( k ) ? (get( k )) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ *
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final int k = ((ok).intValue());
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = put( k, (ov) );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V remove( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = remove( k );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for maps implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
|
|
+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
|
|
+ * is particularly useful for those classes that do not implement their own
|
|
+ * entries (e.g., most immutable maps).
|
|
+ */
|
|
+public abstract class AbstractInt2ObjectMap <V> extends AbstractInt2ObjectFunction <V> implements Int2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractInt2ObjectMap() {}
|
|
+ /** Checks whether the given value is contained in {@link #values()}. */
|
|
+ public boolean containsValue( Object v ) {
|
|
+ return values().contains( v );
|
|
+ }
|
|
+ /** Checks whether the given value is contained in {@link #keySet()}. */
|
|
+ public boolean containsKey( int k ) {
|
|
+ return keySet().contains( k );
|
|
+ }
|
|
+ /** Puts all pairs in the given map.
|
|
+ * If the map implements the interface of this map,
|
|
+ * it uses the faster iterators.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","deprecation"})
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ int n = m.size();
|
|
+ final Iterator<? extends Map.Entry<? extends Integer,? extends V>> i = m.entrySet().iterator();
|
|
+ if (m instanceof Int2ObjectMap) {
|
|
+ Int2ObjectMap.Entry <? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = (Int2ObjectMap.Entry <? extends V>)i.next();
|
|
+ put(e.getIntKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Map.Entry<? extends Integer,? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = i.next();
|
|
+ put(e.getKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
|
|
+ * that do not have entries on their own (e.g., most immutable maps).
|
|
+ *
|
|
+ * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
|
|
+ * would not be reflected in the base map.
|
|
+ */
|
|
+ public static class BasicEntry <V> implements Int2ObjectMap.Entry <V> {
|
|
+ protected int key;
|
|
+ protected V value;
|
|
+ public BasicEntry( final Integer key, final V value ) {
|
|
+ this.key = ((key).intValue());
|
|
+ this.value = (value);
|
|
+ }
|
|
+ public BasicEntry( final int key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue( final V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "->" + value;
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public IntSet keySet() {
|
|
+ return new AbstractIntSet () {
|
|
+ public boolean contains( final int k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractInt2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectMap.this.clear(); }
|
|
+ public IntIterator iterator() {
|
|
+ return new AbstractIntIterator () {
|
|
+ final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public int nextInt() { return ((Int2ObjectMap.Entry <V>)i.next()).getIntKey(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the values of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new AbstractObjectCollection <V>() {
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractInt2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectMap.this.clear(); }
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new AbstractObjectIterator <V>() {
|
|
+ final ObjectIterator<Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V next() { return ((Int2ObjectMap.Entry <V>)i.next()).getValue(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() {
|
|
+ return (ObjectSet)int2ObjectEntrySet();
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * The hash code of a map is computed by summing the hash codes of its entries.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ while( n-- != 0 ) h += i.next().hashCode();
|
|
+ return h;
|
|
+ }
|
|
+ public boolean equals(Object o) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != size() ) return false;
|
|
+ return entrySet().containsAll( m.entrySet() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator<? extends Map.Entry<Integer,V>> i = entrySet().iterator();
|
|
+ int n = size();
|
|
+ Int2ObjectMap.Entry <V> e;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ e = (Int2ObjectMap.Entry <V>)i.next();
|
|
+ s.append(String.valueOf(e.getIntKey()));
|
|
+ s.append("=>");
|
|
+ if (this == e.getValue()) s.append("(this map)"); else
|
|
+ s.append(String.valueOf(e.getValue()));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractInt2ObjectSortedMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
|
|
+public abstract class AbstractInt2ObjectSortedMap <V> extends AbstractInt2ObjectMap <V> implements Int2ObjectSortedMap <V> {
|
|
+ private static final long serialVersionUID = -1773560792952436569L;
|
|
+ protected AbstractInt2ObjectSortedMap() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( final Integer to ) {
|
|
+ return headMap( ((to).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( final Integer from ) {
|
|
+ return tailMap( ((from).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( final Integer from, final Integer to ) {
|
|
+ return subMap( ((from).intValue()), ((to).intValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() {
|
|
+ return (Integer.valueOf(firstIntKey()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() {
|
|
+ return (Integer.valueOf(lastIntKey()));
|
|
+ }
|
|
+ /** Returns a type-specific-sorted-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public IntSortedSet keySet() {
|
|
+ return new KeySet();
|
|
+ }
|
|
+ /** A wrapper exhibiting the keys of a map. */
|
|
+ protected class KeySet extends AbstractIntSortedSet {
|
|
+ public boolean contains( final int k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
|
|
+ public IntComparator comparator() { return AbstractInt2ObjectSortedMap.this.comparator(); }
|
|
+ public int firstInt() { return firstIntKey(); }
|
|
+ public int lastInt() { return lastIntKey(); }
|
|
+ public IntSortedSet headSet( final int to ) { return headMap( to ).keySet(); }
|
|
+ public IntSortedSet tailSet( final int from ) { return tailMap( from ).keySet(); }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return subMap( from, to ).keySet(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
|
|
+ public IntBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on keys.
|
|
+ *
|
|
+ * <P>To provide an iterator on keys, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class KeySetIterator <V> extends AbstractIntBidirectionalIterator {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
|
|
+ public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public int nextInt() { return ((i.next().getKey()).intValue()); };
|
|
+ public int previousInt() { return ((i.previous().getKey()).intValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ }
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new ValuesCollection();
|
|
+ }
|
|
+ /** A wrapper exhibiting the values of a map. */
|
|
+ protected class ValuesCollection extends AbstractObjectCollection <V> {
|
|
+ public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractInt2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractInt2ObjectSortedMap.this.clear(); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on values.
|
|
+ *
|
|
+ * <P>To provide an iterator on values, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Integer, V>> i;
|
|
+ public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Integer, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public V next() { return (i.next().getValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() {
|
|
+ return (ObjectSortedSet)int2ObjectEntrySet();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractIntBidirectionalIterator extends AbstractIntIterator implements IntBidirectionalIterator {
|
|
+ protected AbstractIntBidirectionalIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int previousInt() { return previous().intValue(); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer previous() { return Integer.valueOf( previousInt() ); }
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousInt();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractIntCollection extends AbstractCollection<Integer> implements IntCollection {
|
|
+ protected AbstractIntCollection() {}
|
|
+ public int[] toArray( int a[] ) {
|
|
+ return toIntArray( a );
|
|
+ }
|
|
+ public int[] toIntArray() {
|
|
+ return toIntArray( null );
|
|
+ }
|
|
+ public int[] toIntArray( int a[] ) {
|
|
+ if ( a == null || a.length < size() ) a = new int[ size() ];
|
|
+ IntIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given type-specific collection to this collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ final IntIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.nextInt() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( IntCollection c ) {
|
|
+ final IntIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( ! contains( i.nextInt() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final IntIterator i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.nextInt() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( IntCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final IntIterator i = c.iterator();
|
|
+ while( n-- != 0 ) if ( rem( i.nextInt() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends Integer> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract IntIterator iterator();
|
|
+ /** Delegates to the type-specific <code>rem()</code> method. */
|
|
+ public boolean remove( Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return rem( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean add( final Integer o ) {
|
|
+ return add( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean rem( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return contains( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ final IntIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() ) if ( k == iterator.nextInt() ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ public boolean rem( final int k ) {
|
|
+ final IntIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() )
|
|
+ if ( k == iterator.nextInt() ) {
|
|
+ iterator.remove();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final IntIterator i = iterator();
|
|
+ int n = size();
|
|
+ int k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextInt();
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntComparator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
|
|
+ *
|
|
+ * <P>To create a type-specific comparator you need both a method comparing
|
|
+ * primitive types and a method comparing objects. However, if you have the
|
|
+ * first one you can just inherit from this class and get for free the second
|
|
+ * one.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ */
|
|
+public abstract class AbstractIntComparator implements IntComparator , java.io.Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ protected AbstractIntComparator() {}
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return compare( ok1.intValue(), ok2.intValue() );
|
|
+ }
|
|
+ public abstract int compare( int k1, int k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractIntIterator implements IntIterator {
|
|
+ protected AbstractIntIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int nextInt() { return next().intValue(); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer next() { return Integer.valueOf( nextInt() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextInt();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractIntList extends AbstractIntCollection implements IntList , IntStack {
|
|
+ protected AbstractIntList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public int removeInt( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public int set( final int index, final int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends Integer> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends Integer> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public IntListIterator listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractIntList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = pos++ ); }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractIntList.this.getInt( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ AbstractIntList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractIntList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractIntList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final int k ) {
|
|
+ final IntListIterator i = listIterator();
|
|
+ int e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.nextInt();
|
|
+ if ( ( (k) == (e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final int k ) {
|
|
+ IntListIterator i = listIterator( size() );
|
|
+ int e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previousInt();
|
|
+ if ( ( (k) == (e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (0) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new IntSubList ( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ IntListIterator i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.nextInt();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final int a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final int a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final int a[], int offset, int length ) {
|
|
+ IntListIterator i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.nextInt();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ if ( l instanceof IntList ) {
|
|
+ final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
|
|
+ while( s-- != 0 ) if ( i1.nextInt() != i2.nextInt() ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final List<? extends Integer> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof IntList ) {
|
|
+ final IntListIterator i1 = listIterator(), i2 = ((IntList )l).listIterator();
|
|
+ int r;
|
|
+ int e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.nextInt();
|
|
+ e2 = i2.nextInt();
|
|
+ if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends Integer> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super Integer>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ IntIterator i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ int k = i.nextInt();
|
|
+ h = 31 * h + (k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( int o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public int popInt() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return removeInt( size() - 1 );
|
|
+ }
|
|
+ public int topInt() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return getInt( size() - 1 );
|
|
+ }
|
|
+ public int peekInt( int i ) {
|
|
+ return getInt( size() - 1 - i );
|
|
+ }
|
|
+ public boolean rem( int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeInt( index );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to <code>rem()</code>. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final IntCollection c ) {
|
|
+ return addAll( index, (Collection<? extends Integer>)c );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ return addAll( index, (IntCollection)l );
|
|
+ }
|
|
+ public boolean addAll( final IntCollection c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ public boolean addAll( final IntList l ) {
|
|
+ return addAll( size(), l );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( final int index, final Integer ok ) {
|
|
+ add( index, ok.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer set( final int index, final Integer ok ) {
|
|
+ return (Integer.valueOf(set( index, ok.intValue() )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer get( final int index ) {
|
|
+ return (Integer.valueOf(getInt( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int indexOf( final Object ok) {
|
|
+ return indexOf( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int lastIndexOf( final Object ok ) {
|
|
+ return lastIndexOf( ((((Integer)(ok)).intValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer remove( final int index ) {
|
|
+ return (Integer.valueOf(removeInt( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Integer o ) {
|
|
+ push( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer pop() {
|
|
+ return Integer.valueOf( popInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer top() {
|
|
+ return Integer.valueOf( topInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer peek( int i ) {
|
|
+ return Integer.valueOf( peekInt( i ) );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final IntIterator i = iterator();
|
|
+ int n = size();
|
|
+ int k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextInt();
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class IntSubList extends AbstractIntList implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final IntList l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public IntSubList( final IntList l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public int getInt( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.getInt( from + index );
|
|
+ }
|
|
+ public int removeInt( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.removeInt( from + index );
|
|
+ }
|
|
+ public int set( int index, int k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final int[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getInt( from + ( last = pos++ ) ); }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getInt( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntSubList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new IntSubList ( this, from, to );
|
|
+ }
|
|
+ public boolean rem( int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ to--;
|
|
+ l.removeInt( from + index );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ ensureIndex( index );
|
|
+ to += l.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = this.l.addAll( from + index, l );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return this.l.addAll( from + index, l );
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractIntListIterator extends AbstractIntBidirectionalIterator implements IntListIterator {
|
|
+ protected AbstractIntListIterator() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void set( Integer ok ) { set( ok.intValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( Integer ok ) { add( ok.intValue() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
|
|
+/** An abstract class providing basic methods for priority queues implementing a type-specific interface.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractIntPriorityQueue extends AbstractPriorityQueue<Integer> implements java.io.Serializable, IntPriorityQueue {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public void enqueue( final Integer x ) { enqueue( x.intValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer dequeue() { return (Integer.valueOf(dequeueInt())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() { return (Integer.valueOf(firstInt())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() { return (Integer.valueOf(lastInt())); }
|
|
+ /** Throws an {@link UnsupportedOperationException}. */
|
|
+ public int lastInt() { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractIntSet extends AbstractIntCollection implements Cloneable, IntSet {
|
|
+ protected AbstractIntSet() {}
|
|
+ public abstract IntIterator iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ IntIterator i = iterator();
|
|
+ int k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.nextInt(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += (k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to <code>remove()</code>.
|
|
+ *
|
|
+ * @param k the element to be removed.
|
|
+ * @return true if the set was modified.
|
|
+ */
|
|
+ public boolean rem( int k ) {
|
|
+ return remove( k );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return remove( ((((Integer)(o)).intValue())) );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractIntSortedSet extends AbstractIntSet implements IntSortedSet {
|
|
+ protected AbstractIntSortedSet() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet headSet( final Integer to ) {
|
|
+ return headSet( to.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet tailSet( final Integer from ) {
|
|
+ return tailSet( from.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) {
|
|
+ return subSet( from.intValue(), to.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() {
|
|
+ return (Integer.valueOf(firstInt()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() {
|
|
+ return (Integer.valueOf(lastInt()));
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract IntBidirectionalIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/AbstractIntStack.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.AbstractStack;
|
|
+/** An abstract class providing basic methods for implementing a type-specific stack interface.
|
|
+ *
|
|
+ * <P>To create a type-specific stack, you need both object methods and
|
|
+ * primitive-type methods. However, if you inherit from this class you need
|
|
+ * just one (anyone).
|
|
+ */
|
|
+public abstract class AbstractIntStack extends AbstractStack<Integer> implements IntStack {
|
|
+ protected AbstractIntStack() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Integer o ) {
|
|
+ push( o.intValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer pop() {
|
|
+ return Integer.valueOf( popInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer top() {
|
|
+ return Integer.valueOf( topInt() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Integer peek( int i ) {
|
|
+ return Integer.valueOf( peekInt( i ) );
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public void push( int k ) {
|
|
+ push( Integer.valueOf( k ) );
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int popInt() {
|
|
+ return pop().intValue();
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int topInt() {
|
|
+ return top().intValue();
|
|
+ }
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public int peekInt( int i ) {
|
|
+ return peek( i ).intValue();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectAVLTreeMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific AVL tree map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
|
|
+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
|
|
+ */
|
|
+public class Int2ObjectAVLTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
|
|
+ /** A reference to the root entry. */
|
|
+ protected transient Entry <V> tree;
|
|
+ /** Number of entries in this map. */
|
|
+ protected int count;
|
|
+ /** The first key in this map. */
|
|
+ protected transient Entry <V> firstEntry;
|
|
+ /** The last key in this map. */
|
|
+ protected transient Entry <V> lastEntry;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** The value of this variable remembers, after a <code>put()</code>
|
|
+ * or a <code>remove()</code>, whether the <em>domain</em> of the map
|
|
+ * has been modified. */
|
|
+ protected transient boolean modified;
|
|
+ /** This map's comparator, as provided in the constructor. */
|
|
+ protected Comparator<? super Integer> storedComparator;
|
|
+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
|
|
+ always a type-specific comparator, so it could be derived from the former by wrapping. */
|
|
+ protected transient IntComparator actualComparator;
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ {
|
|
+ allocatePaths();
|
|
+ }
|
|
+ /** Creates a new empty tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap() {
|
|
+ tree = null;
|
|
+ count = 0;
|
|
+ }
|
|
+ /** Generates the comparator that will be actually used.
|
|
+ *
|
|
+ * <P>When a specific {@link Comparator} is specified and stored in {@link
|
|
+ * #storedComparator}, we must check whether it is type-specific. If it is
|
|
+ * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
|
|
+ * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
|
|
+ * and makes it into a type-specific one.
|
|
+ */
|
|
+ private void setActualComparator() {
|
|
+ /* If the provided comparator is already type-specific, we use it. Otherwise,
|
|
+ we use a wrapper anonymous class to fake that it is type-specific. */
|
|
+ if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
|
|
+ else actualComparator = new IntComparator () {
|
|
+ public int compare( int k1, int k2 ) {
|
|
+ return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
|
|
+ }
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return storedComparator.compare( ok1, ok2 );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Creates a new empty tree map with the given comparator.
|
|
+ *
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Comparator<? super Integer> c ) {
|
|
+ this();
|
|
+ storedComparator = c;
|
|
+ setActualComparator();
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a {@link SortedMap} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final SortedMap<Integer,V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Int2ObjectMap <? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a type-specific sorted map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
|
|
+ this( c );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectAVLTreeMap( final int[] k, final V v[] ) {
|
|
+ this( k, v, null );
|
|
+ }
|
|
+ /*
|
|
+ * The following methods implements some basic building blocks used by
|
|
+ * all accessors. They are (and should be maintained) identical to those used in AVLTreeSet.drv.
|
|
+ *
|
|
+ * The put()/remove() code is derived from Ben Pfaff's GNU libavl
|
|
+ * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
|
|
+ * going on, you should have a look at the literate code contained therein
|
|
+ * first.
|
|
+ */
|
|
+ /** Compares two keys in the right way.
|
|
+ *
|
|
+ * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
|
|
+ * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
|
|
+ *
|
|
+ * @param k1 the first key.
|
|
+ * @param k2 the second key.
|
|
+ * @return a number smaller than, equal to or greater than 0, as usual
|
|
+ * (i.e., when k1 < 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectArrayMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A simple, brute-force implementation of a map based on two parallel backing arrays.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
|
|
+ */
|
|
+public class Int2ObjectArrayMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The keys (valid up to {@link #size}, excluded). */
|
|
+ private transient int[] key;
|
|
+ /** The values (parallel to {@link #key}). */
|
|
+ private transient Object[] value;
|
|
+ /** The number of valid entries in {@link #key} and {@link #value}. */
|
|
+ private int size;
|
|
+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int[] key, final Object[] value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ size = key.length;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ }
|
|
+ /** Creates a new empty array map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap() {
|
|
+ this.key = IntArrays.EMPTY_ARRAY;
|
|
+ this.value = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array map of given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int capacity ) {
|
|
+ this.key = new int[ capacity ];
|
|
+ this.value = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ * @param size the number of valid elements in <code>key</code> and <code>value</code>.
|
|
+ */
|
|
+ public Int2ObjectArrayMap( final int[] key, final Object[] value, final int size ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ this.size = size;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
|
|
+ }
|
|
+ private final class EntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ @Override
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
|
|
+ int curr = -1, next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return new AbstractInt2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new AbstractObjectIterator<Int2ObjectMap.Entry <V> >() {
|
|
+ int next = 0, curr = -1;
|
|
+ final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ entry.key = key[ curr = next ];
|
|
+ entry.value = (V) value[ next++ ];
|
|
+ return entry;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( Object o ) {
|
|
+ if ( ! ( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ return Int2ObjectArrayMap.this.containsKey( k ) && ( (Int2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Int2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Override
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ final int oldPos = Int2ObjectArrayMap.this.findKey( k );
|
|
+ if ( oldPos == -1 || ! ( (v) == null ? (Int2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Int2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( Int2ObjectArrayMap.this.key, oldPos + 1, Int2ObjectArrayMap.this.key, oldPos, tail );
|
|
+ System.arraycopy( Int2ObjectArrayMap.this.value, oldPos + 1, Int2ObjectArrayMap.this.value, oldPos, tail );
|
|
+ Int2ObjectArrayMap.this.size--;
|
|
+ Int2ObjectArrayMap.this.value[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ return new EntrySet();
|
|
+ }
|
|
+ private int findKey( final int k ) {
|
|
+ final int[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V get( final int k ) {
|
|
+ final int[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ value[ i ] = null;
|
|
+ }
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsKey( final int k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsValue( Object v ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V put( int k, V v ) {
|
|
+ final int oldKey = findKey( k );
|
|
+ if ( oldKey != -1 ) {
|
|
+ final V oldValue = (V) value[ oldKey ];
|
|
+ value[ oldKey ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ if ( size == key.length ) {
|
|
+ final int[] newKey = new int[ size == 0 ? 2 : size * 2 ];
|
|
+ final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ newKey[ i ] = key[ i ];
|
|
+ newValue[ i ] = value[ i ];
|
|
+ }
|
|
+ key = newKey;
|
|
+ value = newValue;
|
|
+ }
|
|
+ key[ size ] = k;
|
|
+ value[ size ] = v;
|
|
+ size++;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V remove( final int k ) {
|
|
+ final int oldPos = findKey( k );
|
|
+ if ( oldPos == -1 ) return defRetValue;
|
|
+ final V oldValue = (V) value[ oldPos ];
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( key, oldPos + 1, key, oldPos, tail );
|
|
+ System.arraycopy( value, oldPos + 1, value, oldPos, tail );
|
|
+ size--;
|
|
+ value[ size ] = null;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @Override
|
|
+ public IntSet keySet() {
|
|
+ return new IntArraySet ( key, size );
|
|
+ }
|
|
+ @Override
|
|
+ public ObjectCollection <V> values() {
|
|
+ return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectArrayMap <V> clone() {
|
|
+ Int2ObjectArrayMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectArrayMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ s.writeInt( key[ i ] );
|
|
+ s.writeObject( value[ i ] );
|
|
+ }
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ key = new int[ size ];
|
|
+ value = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ key[ i ] = s.readInt();
|
|
+ value[ i ] = s.readObject();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunction.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Function;
|
|
+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
|
|
+ * a key. Rather, they return a {@linkplain #defaultReturnValue() default
|
|
+ * return value}, which is set to 0 cast to the return type (<code>false</code>
|
|
+ * for booleans) at creation, but can be changed using the
|
|
+ * <code>defaultReturnValue()</code> method.
|
|
+ *
|
|
+ * <P>For uniformity reasons, even maps returning objects implement the default
|
|
+ * return value (of course, in this case the default return value is
|
|
+ * initialized to <code>null</code>).
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
|
|
+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
|
|
+ * that standard versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> for maps with primitive-type values <em>return
|
|
+ * <code>null</code> to denote missing keys</em> rather than wrap the default
|
|
+ * return value in an object (of course, for maps with object keys and values
|
|
+ * this is not possible, as there is no type-specific version).
|
|
+ *
|
|
+ * @see Function
|
|
+ */
|
|
+public interface Int2ObjectFunction <V> extends Function<Integer, V> {
|
|
+ /** Adds a pair to the map.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#put(Object,Object)
|
|
+ */
|
|
+ V put( int key, V value );
|
|
+ /** Returns the value to which the given key is mapped.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#get(Object)
|
|
+ */
|
|
+ V get( int key );
|
|
+ /** Removes the mapping with the given key.
|
|
+ * @param key the key.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#remove(Object)
|
|
+ */
|
|
+ V remove( int key );
|
|
+ /**
|
|
+ * @see Function#containsKey(Object)
|
|
+ */
|
|
+ boolean containsKey( int key );
|
|
+ /** Sets the default return value.
|
|
+ *
|
|
+ * This value must be returned by type-specific versions of
|
|
+ * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
|
|
+ * denote that the map does not contain the specified key. It must be
|
|
+ * 0/<code>false</code>/<code>null</code> by default.
|
|
+ *
|
|
+ * @param rv the new default return value.
|
|
+ * @see #defaultReturnValue()
|
|
+ */
|
|
+ void defaultReturnValue( V rv );
|
|
+ /** Gets the default return value.
|
|
+ *
|
|
+ * @return the current default return value.
|
|
+ */
|
|
+ V defaultReturnValue();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectFunctions.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with type-specific functions.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Function
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectFunctions {
|
|
+ private Int2ObjectFunctions() {}
|
|
+ /** An immutable class representing an empty type-specific function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class EmptyFunction <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyFunction() {}
|
|
+ public V get( final int k ) { return (null); }
|
|
+ public boolean containsKey( final int k ) { return false; }
|
|
+ public V defaultReturnValue() { return (null); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return null; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ private Object readResolve() { return EMPTY_FUNCTION; }
|
|
+ public Object clone() { return EMPTY_FUNCTION; }
|
|
+ }
|
|
+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
|
|
+ /** An immutable class representing a type-specific singleton function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class Singleton <V> extends AbstractInt2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final int key;
|
|
+ protected final V value;
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ public boolean containsKey( final int k ) { return ( (key) == (k) ); }
|
|
+ public V get( final int k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectLinkedOpenHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+/** A type-specific linked hash map with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
|
|
+ * have been added to the map (addition of pairs whose key is already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted map, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first key
|
|
+ * in iteration order with {@code firstKey()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
|
|
+ * contract because all submap methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class using are type-specific
|
|
+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is a key of the map</em>, or
|
|
+ * a {@link NoSuchElementException} exception will be thrown.
|
|
+ * If, however, the provided element is not the first or last key in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire key set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectLinkedOpenHashMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastSortedEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectLinkedOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectLinkedOpenHashMap( final int[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ private V setValue( final int pos, final V v ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Removes the mapping associated with the first key in iteration order.
|
|
+ * @return the value previously associated with the first key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeFirst() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ /** Removes the mapping associated with the last key in iteration order.
|
|
+ * @return the value previously associated with the last key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeLast() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToFirst( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToLast( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToFirst( final int k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToLast( final int k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * <P>This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first key of this map in iteration order.
|
|
+ *
|
|
+ * @return the first key in iteration order.
|
|
+ */
|
|
+ public int firstIntKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last key of this map in iteration order.
|
|
+ *
|
|
+ * @return the last key in iteration order.
|
|
+ */
|
|
+ public int lastIntKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ public Int2ObjectSortedMap <V> tailMap( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectSortedMap <V> headMap( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectSortedMap <V> subMap( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ /** A list iterator over a linked map.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
|
|
+ */
|
|
+ private class MapIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
|
|
+ int index = -1;
|
|
+ private MapIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ private MapIterator( final int from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( Int2ObjectLinkedOpenHashMap.this.containsNullKey ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return curr;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ Int2ObjectLinkedOpenHashMap.this.containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public EntryIterator() {}
|
|
+ public EntryIterator( int from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ return entry = new MapEntry( previousEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Int2ObjectMap.Entry <V> > {
|
|
+ final MapEntry entry = new MapEntry();
|
|
+ public FastEntryIterator() {}
|
|
+ public FastEntryIterator( int from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ entry.index = previousEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public void set( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Int2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSortedSet<Int2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public Comparator<? super Int2ObjectMap.Entry <V> > comparator() { return null; }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > subSet( Int2ObjectMap.Entry <V> fromElement, Int2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > headSet( Int2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > tailSet( Int2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
|
|
+ public Int2ObjectMap.Entry <V> first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Int2ObjectLinkedOpenHashMap.this.first );
|
|
+ }
|
|
+ public Int2ObjectMap.Entry <V> last() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Int2ObjectLinkedOpenHashMap.this.last );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Int2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > iterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( final Int2ObjectMap.Entry <V> from ) {
|
|
+ return new FastEntryIterator( from.getIntKey() );
|
|
+ }
|
|
+ }
|
|
+ public FastSortedEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntListIterator {
|
|
+ public KeyIterator( final int k ) { super( k ); }
|
|
+ public int previousInt() { return key[ previousEntry() ]; }
|
|
+ public void set( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer previous() { return (Integer.valueOf(key[ previousEntry() ])); }
|
|
+ public void set( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Integer ok ) { throw new UnsupportedOperationException(); }
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSortedSet {
|
|
+ public IntListIterator iterator( final int from ) {
|
|
+ return new KeyIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectLinkedOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ final public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ final public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ final public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public IntSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
|
|
+ public V previous() { return value[ previousEntry() ]; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectLinkedOpenHashMap <V> clone() {
|
|
+ Int2ObjectLinkedOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectLinkedOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = (key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Map;
|
|
+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
|
|
+ *
|
|
+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
|
|
+ *
|
|
+ * <P>A submap or subset may or may not have an
|
|
+ * independent default return value (which however must be initialized to the
|
|
+ * default return value of the originator).
|
|
+ *
|
|
+ * @see Map
|
|
+ */
|
|
+public interface Int2ObjectMap <V> extends Int2ObjectFunction <V>, Map<Integer,V> {
|
|
+ /** An entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastEntrySet <V> extends ObjectSet<Int2ObjectMap.Entry <V> > {
|
|
+ /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
|
|
+ */
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator();
|
|
+ }
|
|
+ /** Returns a set view of the mappings contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
|
|
+ *
|
|
+ * @return a set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSet<Map.Entry<Integer, V>> entrySet();
|
|
+ /** Returns a type-specific set view of the mappings contained in this map.
|
|
+ *
|
|
+ * <p>This method is necessary because there is no inheritance along
|
|
+ * type parameters: it is thus impossible to strengthen {@link #entrySet()}
|
|
+ * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
|
|
+ * of type-specific entries (the latter makes it possible to
|
|
+ * access keys and values with type-specific methods).
|
|
+ *
|
|
+ * @return a type-specific set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
|
|
+ /** Returns a set view of the keys contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
|
|
+ *
|
|
+ * @return a set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ IntSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * @see java.util.Map.Entry
|
|
+ */
|
|
+ interface Entry <V> extends Map.Entry <Integer,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ Integer getKey();
|
|
+ /**
|
|
+ * @see java.util.Map.Entry#getKey()
|
|
+ */
|
|
+ int getIntKey();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectMaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import java.util.Map;
|
|
+/** A class providing static methods and objects that do useful things with type-specific maps.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Maps
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectMaps {
|
|
+ private Int2ObjectMaps() {}
|
|
+ /** An immutable class representing an empty type-specific map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class EmptyMap <V> extends Int2ObjectFunctions.EmptyFunction <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyMap() {}
|
|
+ public boolean containsValue( final Object v ) { return false; }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
|
|
+
|
|
+ public IntSet keySet() { return IntSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_MAP; }
|
|
+ public Object clone() { return EMPTY_MAP; }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ return ((Map<?,?>)o).isEmpty();
|
|
+ }
|
|
+ public String toString() { return "{}"; }
|
|
+ }
|
|
+ /** An empty type-specific map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
|
|
+ /** Return an empty map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Int2ObjectMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Int2ObjectFunctions.Singleton <V> implements Int2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected transient ObjectSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ protected transient IntSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ super( key, value );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
|
|
+ public void putAll( final Map<? extends Integer, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
|
|
+ public IntSet keySet() { if ( keys == null ) keys = IntSets.singleton( key ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
|
|
+ protected class SingletonEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() { return (Integer.valueOf(Singleton.this.key)); }
|
|
+ public V getValue() { return (Singleton.this.value); }
|
|
+ public int getIntKey() { return Singleton.this.key; }
|
|
+ public V setValue( final V value ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (Singleton.this.key) == (((((Integer)(e.getKey())).intValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() { return (Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
|
|
+ public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
|
|
+ }
|
|
+ public boolean isEmpty() { return false; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSet)int2ObjectEntrySet(); }
|
|
+ public int hashCode() { return (key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != 1 ) return false;
|
|
+ return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
|
|
+ }
|
|
+ public String toString() { return "{" + key + "=>" + value + "}"; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenCustomHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectOpenCustomHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The hash strategy of this custom map. */
|
|
+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Map<? extends Integer, ? extends V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final Int2ObjectMap <V> m, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( k.length, f, strategy );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenCustomHashMap( final int[] k, final V[] v, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash map.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( strategy.equals( (key[ index ]), (((e.getKey()).intValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Int2ObjectOpenCustomHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ IntArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final int key[] = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final int k = wrapped.getInt( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Int2ObjectOpenCustomHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Int2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return ( Int2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSet {
|
|
+ public IntIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectOpenCustomHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public IntSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenCustomHashMap <V> clone() {
|
|
+ Int2ObjectOpenCustomHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectOpenCustomHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = ( strategy.hashCode(key[ i ]) );
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectOpenHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Int2ObjectOpenHashMap <V> extends AbstractInt2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final Int2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectOpenHashMap( final int[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Integer,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final int k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final int k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Integer ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).intValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final int k = ((((Integer)(ok)).intValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Integer ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final int k = ((ok).intValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final int key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Int2ObjectMap.Entry <V>, Map.Entry<Integer, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer getKey() {
|
|
+ return (Integer.valueOf(key[ index ]));
|
|
+ }
|
|
+ public int getIntKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).intValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return (key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Int2ObjectOpenHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ IntArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final int key[] = Int2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final int k = wrapped.getInt( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new IntArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Int2ObjectOpenHashMap.this.remove( wrapped.getInt( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Int2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Int2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Int2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Int2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Int2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Integer, V> e = (Map.Entry<Integer, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final int k = ((e.getKey()).intValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = Int2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> int2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements IntIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public int nextInt() { return key[ nextEntry() ]; }
|
|
+ public Integer next() { return (Integer.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractIntSet {
|
|
+ public IntIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( int k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( int k ) {
|
|
+ final int oldSize = size;
|
|
+ Int2ObjectOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public IntSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Int2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectOpenHashMap <V> clone() {
|
|
+ Int2ObjectOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Int2ObjectOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = (key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final int key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeInt( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ int k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectRBTreeMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific red-black tree map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class are type-specific {@linkplain
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ * Moreover, the iterator returned by <code>iterator()</code> can be safely cast
|
|
+ * to a type-specific {@linkplain java.util.ListIterator list iterator}.
|
|
+ *
|
|
+ */
|
|
+public class Int2ObjectRBTreeMap <V> extends AbstractInt2ObjectSortedMap <V> implements java.io.Serializable, Cloneable {
|
|
+ /** A reference to the root entry. */
|
|
+ protected transient Entry <V> tree;
|
|
+ /** Number of entries in this map. */
|
|
+ protected int count;
|
|
+ /** The first key in this map. */
|
|
+ protected transient Entry <V> firstEntry;
|
|
+ /** The last key in this map. */
|
|
+ protected transient Entry <V> lastEntry;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient ObjectSortedSet<Int2ObjectMap.Entry <V> > entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient IntSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** The value of this variable remembers, after a <code>put()</code>
|
|
+ * or a <code>remove()</code>, whether the <em>domain</em> of the map
|
|
+ * has been modified. */
|
|
+ protected transient boolean modified;
|
|
+ /** This map's comparator, as provided in the constructor. */
|
|
+ protected Comparator<? super Integer> storedComparator;
|
|
+ /** This map's actual comparator; it may differ from {@link #storedComparator} because it is
|
|
+ always a type-specific comparator, so it could be derived from the former by wrapping. */
|
|
+ protected transient IntComparator actualComparator;
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ {
|
|
+ allocatePaths();
|
|
+ }
|
|
+ /** Creates a new empty tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap() {
|
|
+ tree = null;
|
|
+ count = 0;
|
|
+ }
|
|
+ /** Generates the comparator that will be actually used.
|
|
+ *
|
|
+ * <P>When a specific {@link Comparator} is specified and stored in {@link
|
|
+ * #storedComparator}, we must check whether it is type-specific. If it is
|
|
+ * so, we can used directly, and we store it in {@link #actualComparator}. Otherwise,
|
|
+ * we generate on-the-fly an anonymous class that wraps the non-specific {@link Comparator}
|
|
+ * and makes it into a type-specific one.
|
|
+ */
|
|
+ private void setActualComparator() {
|
|
+ /* If the provided comparator is already type-specific, we use it. Otherwise,
|
|
+ we use a wrapper anonymous class to fake that it is type-specific. */
|
|
+ if ( storedComparator == null || storedComparator instanceof IntComparator ) actualComparator = (IntComparator)storedComparator;
|
|
+ else actualComparator = new IntComparator () {
|
|
+ public int compare( int k1, int k2 ) {
|
|
+ return storedComparator.compare( (Integer.valueOf(k1)), (Integer.valueOf(k2)) );
|
|
+ }
|
|
+ public int compare( Integer ok1, Integer ok2 ) {
|
|
+ return storedComparator.compare( ok1, ok2 );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Creates a new empty tree map with the given comparator.
|
|
+ *
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Comparator<? super Integer> c ) {
|
|
+ this();
|
|
+ storedComparator = c;
|
|
+ setActualComparator();
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Map<? extends Integer, ? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a {@link SortedMap} to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final SortedMap<Integer,V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given map.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Int2ObjectMap <? extends V> m ) {
|
|
+ this();
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map copying a given sorted map (and its {@link Comparator}).
|
|
+ *
|
|
+ * @param m a type-specific sorted map to be copied into the new tree map.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final Int2ObjectSortedMap <V> m ) {
|
|
+ this( m.comparator() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays and the given comparator.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @param c a (possibly type-specific) comparator.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final int[] k, final V v[], final Comparator<? super Integer> c ) {
|
|
+ this( c );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new tree map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new tree map.
|
|
+ * @param v the array of corresponding values in the new tree map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Int2ObjectRBTreeMap( final int[] k, final V v[] ) {
|
|
+ this( k, v, null );
|
|
+ }
|
|
+ /*
|
|
+ * The following methods implements some basic building blocks used by
|
|
+ * all accessors. They are (and should be maintained) identical to those used in RBTreeSet.drv.
|
|
+ *
|
|
+ * The put()/remove() code is derived from Ben Pfaff's GNU libavl
|
|
+ * (http://www.msu.edu/~pfaffben/avl/). If you want to understand what's
|
|
+ * going on, you should have a look at the literate code contained therein
|
|
+ * first.
|
|
+ */
|
|
+ /** Compares two keys in the right way.
|
|
+ *
|
|
+ * <P>This method uses the {@link #actualComparator} if it is non-<code>null</code>.
|
|
+ * Otherwise, it resorts to primitive type comparisons or to {@link Comparable#compareTo(Object) compareTo()}.
|
|
+ *
|
|
+ * @param k1 the first key.
|
|
+ * @param k2 the second key.
|
|
+ * @return a number smaller than, equal to or greater than 0, as usual
|
|
+ * (i.e., when k1 < 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()}, {@link #values()},
|
|
+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap
|
|
+ */
|
|
+public interface Int2ObjectSortedMap <V> extends Int2ObjectMap <V>, SortedMap<Integer, V> {
|
|
+ /** A sorted entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of entry objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Int2ObjectMap.Entry <V> >, FastEntrySet <V> {
|
|
+ /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ */
|
|
+ public ObjectBidirectionalIterator<Int2ObjectMap.Entry <V> > fastIterator( Int2ObjectMap.Entry <V> from );
|
|
+ }
|
|
+ /** Returns a sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Map.Entry<Integer, V>> entrySet();
|
|
+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet();
|
|
+ /** Returns a sorted-set view of the keys contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ IntSortedSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link SortedMap}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
|
|
+ *
|
|
+ * @see SortedMap#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> subMap(Integer fromKey, Integer toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> headMap(Integer toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> tailMap(Integer fromKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> subMap(int fromKey, int toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> headMap(int toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Int2ObjectSortedMap <V> tailMap(int fromKey);
|
|
+ /**
|
|
+ * @see SortedMap#firstKey()
|
|
+ */
|
|
+ int firstIntKey();
|
|
+ /**
|
|
+ * @see SortedMap#lastKey()
|
|
+ */
|
|
+ int lastIntKey();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/Int2ObjectSortedMaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
|
|
+import java.util.Comparator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Int2ObjectSortedMaps {
|
|
+ private Int2ObjectSortedMaps() {}
|
|
+ /** Returns a comparator for entries based on a given comparator on keys.
|
|
+ *
|
|
+ * @param comparator a comparator on keys.
|
|
+ * @return the associated comparator on entries.
|
|
+ */
|
|
+ public static Comparator<? super Map.Entry<Integer, ?>> entryComparator( final IntComparator comparator ) {
|
|
+ return new Comparator<Map.Entry<Integer, ?>>() {
|
|
+ public int compare( Map.Entry<Integer, ?> x, Map.Entry<Integer, ?> y ) {
|
|
+ return comparator.compare( x.getKey(), y.getKey() );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class EmptySortedMap <V> extends Int2ObjectMaps.EmptyMap <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySortedMap() {}
|
|
+ public IntComparator comparator() { return null; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet keySet() { return IntSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { return EMPTY_MAP; }
|
|
+ public int firstIntKey() { throw new NoSuchElementException(); }
|
|
+ public int lastIntKey() { throw new NoSuchElementException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
|
|
+ }
|
|
+ /** An empty sorted map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
|
|
+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty sorted map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Int2ObjectSortedMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Int2ObjectMaps.Singleton <V> implements Int2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntComparator comparator;
|
|
+ protected Singleton( final int key, final V value, IntComparator comparator ) {
|
|
+ super( key, value );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ protected Singleton( final int key, final V value ) {
|
|
+ this( key, value, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final int k1, final int k2 ) {
|
|
+ return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ public IntComparator comparator() { return comparator; }
|
|
+
|
|
+ public ObjectSortedSet<Int2ObjectMap.Entry <V> > int2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Int2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Int2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Int2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Integer, V>> entrySet() { return (ObjectSortedSet)int2ObjectEntrySet(); }
|
|
+ public IntSortedSet keySet() { if ( keys == null ) keys = IntSortedSets.singleton( key, comparator ); return (IntSortedSet )keys; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> subMap( final int from, final int to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> headMap( final int to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Int2ObjectSortedMap <V> tailMap( final int from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
|
|
+ public int firstIntKey() { return key; }
|
|
+ public int lastIntKey() { return key; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> headMap( Integer oto ) { return headMap( ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> tailMap( Integer ofrom ) { return tailMap( ((ofrom).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Int2ObjectSortedMap <V> subMap( Integer ofrom, Integer oto ) { return subMap( ((ofrom).intValue()), ((oto).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer firstKey() { return (Integer.valueOf(firstIntKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer lastKey() { return (Integer.valueOf(lastIntKey())); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayFIFOQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.io.Serializable;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based FIFO queue, supporting also deque operations.
|
|
+ *
|
|
+ * <P>Instances of this class represent a FIFO queue using a backing
|
|
+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
|
|
+ * to reduce its memory usage, if necessary.
|
|
+ *
|
|
+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
|
|
+ */
|
|
+public class IntArrayFIFOQueue extends AbstractIntPriorityQueue implements Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ /** The standard initial capacity of a queue. */
|
|
+ public final static int INITIAL_CAPACITY = 4;
|
|
+ /** The backing array. */
|
|
+ protected transient int array[];
|
|
+ /** The current (cached) length of {@link #array}. */
|
|
+ protected transient int length;
|
|
+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
|
|
+ protected transient int start;
|
|
+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
|
|
+ * Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
|
|
+ protected transient int end;
|
|
+ /** Creates a new empty queue with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+
|
|
+ public IntArrayFIFOQueue( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ array = new int[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
|
|
+ length = array.length;
|
|
+ }
|
|
+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
|
|
+ */
|
|
+ public IntArrayFIFOQueue() {
|
|
+ this( INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Returns <code>null</code> (FIFO queues have no comparator).
|
|
+ * @return <code>null</code>.
|
|
+ */
|
|
+ @Override
|
|
+ public IntComparator comparator() {
|
|
+ return null;
|
|
+ }
|
|
+ @Override
|
|
+ public int dequeueInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ final int t = array[ start ];
|
|
+ if ( ++start == length ) start = 0;
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+ /** Dequeues the last element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ public int dequeueLastInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ if ( end == 0 ) end = length;
|
|
+ final int t = array[ --end ];
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+
|
|
+ private final void resize( final int size, final int newLength ) {
|
|
+ final int[] newArray = new int[ newLength ];
|
|
+ if ( start >= end ) {
|
|
+ if ( size != 0 ) {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ }
|
|
+ else System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ start = 0;
|
|
+ end = size;
|
|
+ array = newArray;
|
|
+ length = newLength;
|
|
+ }
|
|
+ private final void expand() {
|
|
+ resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
|
|
+ }
|
|
+ private final void reduce() {
|
|
+ final int size = size();
|
|
+ if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
|
|
+ }
|
|
+ @Override
|
|
+ public void enqueue( int x ) {
|
|
+ array[ end++ ] = x;
|
|
+ if ( end == length ) end = 0;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
|
|
+ */
|
|
+ public void enqueueFirst( int x ) {
|
|
+ if ( start == 0 ) start = length;
|
|
+ array[ --start ] = x;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Returns the first element of the queue.
|
|
+ * @return the first element of the queue.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ start ];
|
|
+ }
|
|
+ /** Returns the last element of the queue.
|
|
+ * @return the last element of the queue.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ ( end == 0 ? length : end ) - 1 ];
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ start = end = 0;
|
|
+ }
|
|
+ /** Trims the queue to the smallest possible size. */
|
|
+
|
|
+ public void trim() {
|
|
+ final int size = size();
|
|
+ final int[] newArray =
|
|
+ new int[ size + 1 ];
|
|
+ if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ else {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ start = 0;
|
|
+ length = ( end = size ) + 1;
|
|
+ array = newArray;
|
|
+ }
|
|
+ @Override
|
|
+ public int size() {
|
|
+ final int apparentLength = end - start;
|
|
+ return apparentLength >= 0 ? apparentLength : length + apparentLength;
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ int size = size();
|
|
+ s.writeInt( size );
|
|
+ for( int i = start; size-- != 0; ) {
|
|
+ s.writeInt( array[ i++ ] );
|
|
+ if ( i == length ) i = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ end = s.readInt();
|
|
+ array = new int[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
|
|
+ for( int i = 0; i < end; i++ ) array[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayIndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based semi-indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use as reference list a <em>reference array</em>,
|
|
+ * which must be provided to each constructor, and represent a priority queue
|
|
+ * using a backing array of integer indices—all operations are performed
|
|
+ * directly on the array. The array is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small. Moreover, it allows to enqueue several
|
|
+ * time the same index, without limitations.
|
|
+ */
|
|
+public class IntArrayIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
|
|
+ /** The reference array. */
|
|
+ protected int refArray[];
|
|
+ /** The backing array. */
|
|
+ protected int array[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue without elements with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new int[ capacity ];
|
|
+ this.refArray = refArray;
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntArrayIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ /** Returns the index (in {@link #array}) of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ int first = refArray[ array[ firstIndex ] ];
|
|
+ if ( c == null ) while( i-- != 0 ) { if ( ( (refArray[ array[ i ] ]) < (first) ) ) first = refArray[ array[ firstIndex = i ] ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( refArray[ array[ i ] ], first ) < 0 ) first = refArray[ array[ firstIndex = i ] ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ /** Returns the index (in {@link #array}) of the largest element. */
|
|
+
|
|
+ private int findLast() {
|
|
+ int i = size;
|
|
+ int lastIndex = --i;
|
|
+ int last = refArray[ array[ lastIndex ] ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (last) < (refArray[ array[ i ] ]) ) ) last = refArray[ array[ lastIndex = i ] ]; }
|
|
+ else { while( i-- != 0 ) if ( c.compare( last, refArray[ array[ i ] ] ) < 0 ) last = refArray[ array[ lastIndex = i ] ]; }
|
|
+ return lastIndex;
|
|
+ }
|
|
+ protected final void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+ /** Ensures that the given index is a firstIndexValid reference.
|
|
+ *
|
|
+ * @param index an index in the reference array.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
|
|
+ */
|
|
+ protected void ensureElement( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
|
|
+ }
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
|
|
+ * when <code>x</code> is already in the queue. However, the queue state will become
|
|
+ * inconsistent and the following behaviour will not be predictable.
|
|
+ */
|
|
+
|
|
+ public void enqueue( int x ) {
|
|
+ ensureElement( x );
|
|
+ if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (refArray[ x ]) < (refArray[ array[ firstIndex ] ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( refArray[ x ], refArray[ array[ firstIndex ] ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ ensureNonEmpty();
|
|
+ final int firstIndex = findFirst();
|
|
+ final int result = array[ firstIndex ];
|
|
+ if ( --size != 0 ) System.arraycopy( array, firstIndex + 1, array, firstIndex, size - firstIndex );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public int first() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public int last() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findLast() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ *
|
|
+ * <P>Note that for efficiency reasons this method will <em>not</em> throw an exception
|
|
+ * when <code>index</code> is not in the queue.
|
|
+ */
|
|
+ public void changed( int index ) {
|
|
+ ensureElement( index );
|
|
+ if ( index == firstIndex ) firstIndexValid = false;
|
|
+ }
|
|
+ public void allChanged() {
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public boolean remove( int index ) {
|
|
+ ensureElement( index );
|
|
+ final int[] a = array;
|
|
+ int i = size;
|
|
+ while( i-- != 0 ) if ( a[ i ] == index ) break;
|
|
+ if ( i < 0 ) return false;
|
|
+ firstIndexValid = false;
|
|
+ if ( --size != 0 ) System.arraycopy( a, i + 1, a, i, size - i );
|
|
+ return true;
|
|
+ }
|
|
+ public int front( int[] a ) {
|
|
+ final int top = refArray[ array[ findFirst() ] ];
|
|
+ int i = size, c = 0;
|
|
+ while( i-- != 0 ) if ( ( (top) == (refArray[ array[ i ] ]) ) ) a[ c++ ] = array[ i ];
|
|
+ return c;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() { size = 0; firstIndexValid = false; }
|
|
+ /** Trims the backing array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = IntArrays.trim( array, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ public String toString() {
|
|
+ StringBuffer s = new StringBuffer();
|
|
+ s.append( "[" );
|
|
+ for ( int i = 0; i < size; i++ ) {
|
|
+ if ( i != 0 ) s.append( ", " );
|
|
+ s.append( refArray[ array [ i ] ] );
|
|
+ }
|
|
+ s.append( "]" );
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling its current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible. The backing array is exposed by the
|
|
+ * {@link #elements()} method.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class IntArrayList extends AbstractIntList implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353130L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** The backing array. */
|
|
+ protected transient int a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected IntArrayList( final int a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+
|
|
+ public IntArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = new int[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public IntArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final Collection<? extends Integer> c ) {
|
|
+ this( c.size() );
|
|
+ size = IntIterators.unwrap( IntIterators.asIntIterator( c.iterator() ), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntCollection c ) {
|
|
+ this( c.size() );
|
|
+ size = IntIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntList l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final int a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public IntArrayList( final int a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final Iterator<? extends Integer> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public IntArrayList( final IntIterator i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.nextInt() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public int[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static IntArrayList wrap( final int a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final IntArrayList l = new IntArrayList ( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static IntArrayList wrap( final int a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ a = IntArrays.ensureCapacity( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ private void grow( final int capacity ) {
|
|
+ a = IntArrays.grow( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final int k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public int getInt( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final int k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final int k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int removeInt( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final int old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final int k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeInt( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public int set( final int index, final int k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ int old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final int t[] = new int[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final int[] a, final int offset, final int length ) {
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final int a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ public int[] toIntArray( int a[] ) {
|
|
+ if ( a == null || a.length < size ) a = new int[ size ];
|
|
+ System.arraycopy( this.a, 0, a, 0, size );
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( int index, final IntCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ final IntIterator i = c.iterator();
|
|
+ size += n;
|
|
+ while( n-- != 0 ) a[ index++ ] = i.nextInt();
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean addAll( final int index, final IntList l ) {
|
|
+ ensureIndex( index );
|
|
+ final int n = l.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ l.getElements( 0, a, index, n );
|
|
+ size += n;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final IntCollection c ) {
|
|
+ final int[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final int[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( (Integer.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public IntListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractIntListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public int nextInt() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public int previousInt() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( int k ) {
|
|
+ IntArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( int k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ IntArrayList.this.removeInt( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public IntArrayList clone() {
|
|
+ IntArrayList c = new IntArrayList ( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final IntArrayList l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final int[] a1 = a;
|
|
+ final int[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final IntArrayList l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final int a1[] = a, a2[] = l.a;
|
|
+ int e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( Integer.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new int[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrayPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a backing
|
|
+ * array—all operations are performed directly on the array. The array is
|
|
+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
|
|
+ * to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small.
|
|
+ */
|
|
+public class IntArrayPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array. */
|
|
+
|
|
+ protected transient int array[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ transient protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ transient protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public IntArrayPriorityQueue( int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( IntComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, int size, final IntComparator c ) {
|
|
+ this( c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, final IntComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public IntArrayPriorityQueue( final int[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Returns the index of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ int first = array[ firstIndex ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ private void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+
|
|
+ public void enqueue( int x ) {
|
|
+ if ( size == array.length ) array = IntArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public int dequeueInt() {
|
|
+ ensureNonEmpty();
|
|
+ final int first = findFirst();
|
|
+ final int result = array[ first ];
|
|
+ System.arraycopy( array, first + 1, array, first, --size - first );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = IntArrays.trim( array, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( array.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( array[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ array = new int[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) array[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArraySet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class IntArraySet extends AbstractIntSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient int[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public IntArraySet( final int[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public IntArraySet() {
|
|
+ this.a = IntArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public IntArraySet( final int capacity ) {
|
|
+ this.a = new int[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public IntArraySet( IntCollection c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public IntArraySet( final Collection<? extends Integer> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public IntArraySet( final int[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final int o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ public IntIterator iterator() {
|
|
+ return new AbstractIntIterator () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final int k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final int k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final int k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final int[] b = new int[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntArraySet clone() {
|
|
+ IntArraySet c;
|
|
+ try {
|
|
+ c = (IntArraySet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new int[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntArrays.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import java.util.concurrent.Callable;
|
|
+import java.util.concurrent.ExecutorCompletionService;
|
|
+import java.util.concurrent.ExecutorService;
|
|
+import java.util.concurrent.Executors;
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
|
|
+ * contain several methods make it possible to load and save arrays of primitive types as sequences
|
|
+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
|
|
+ * to sort an array using the values in another array as comparator.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
|
|
+ * on random-looking data. In
|
|
+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
|
|
+ * exploits parallelism better.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class IntArrays {
|
|
+ private IntArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static int[] EMPTY_ARRAY = {};
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static int[] ensureCapacity( final int[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int t[] =
|
|
+ new int[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static int[] ensureCapacity( final int[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final int t[] =
|
|
+ new int[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface IntBidirectionalIterator extends IntIterator , ObjectBidirectionalIterator<Integer> {
|
|
+ /**
|
|
+ * Returns the previous element as a primitive type.
|
|
+ *
|
|
+ * @return the previous element in the iteration.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+ int previousInt();
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface IntCollection extends Collection<Integer>, IntIterable {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ IntIterator iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntIterator intIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+ /**
|
|
+ * @see Collection#contains(Object)
|
|
+ */
|
|
+ boolean contains( int key );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray()
|
|
+ */
|
|
+ int[] toIntArray();
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ int[] toIntArray( int a[] );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ int[] toArray( int a[] );
|
|
+ /**
|
|
+ * @see Collection#add(Object)
|
|
+ */
|
|
+ boolean add( int key );
|
|
+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface
|
|
+ * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
|
|
+ * <code>remove()</code>.
|
|
+ *
|
|
+ * @see Collection#remove(Object)
|
|
+ */
|
|
+ boolean rem( int key );
|
|
+ /**
|
|
+ * @see Collection#addAll(Collection)
|
|
+ */
|
|
+ boolean addAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#containsAll(Collection)
|
|
+ */
|
|
+ boolean containsAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#removeAll(Collection)
|
|
+ */
|
|
+ boolean removeAll( IntCollection c );
|
|
+ /**
|
|
+ * @see Collection#retainAll(Collection)
|
|
+ */
|
|
+ boolean retainAll( IntCollection c );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntCollections.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntCollections {
|
|
+ private IntCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection extends AbstractIntCollection {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( int k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public int[] toIntArray( int[] a ) { return a; }
|
|
+ public int[] toIntArray() { return IntArrays.EMPTY_ARRAY; }
|
|
+ public boolean rem( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( IntCollection c ) { return c.isEmpty(); }
|
|
+
|
|
+ public IntBidirectionalIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection implements IntCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntCollection collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final IntCollection c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final IntCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final int o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public int[] toIntArray() { synchronized( sync ) { return collection.toIntArray(); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public int[] toIntArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
|
|
+ public int[] toArray( final int[] a ) { synchronized( sync ) { return collection.toIntArray( a ); } }
|
|
+ public boolean addAll( final IntCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final IntCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final IntCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final IntCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public boolean add( final Integer k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public IntIterator iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ public boolean add( final int k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final int k ) { synchronized( sync ) { return collection.rem( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection synchronize( final IntCollection c ) { return new SynchronizedCollection ( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection synchronize( final IntCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection implements IntCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntCollection collection;
|
|
+ protected UnmodifiableCollection( final IntCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final int o ) { return collection.contains( o ); }
|
|
+ public IntIterator iterator() { return IntIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ public int[] toIntArray() { return collection.toIntArray(); }
|
|
+ public int[] toIntArray( final int[] a ) { return collection.toIntArray( a ); }
|
|
+ public int[] toArray( final int[] a ) { return collection.toArray( a ); }
|
|
+ public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final IntCollection c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return collection.contains( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static IntCollection unmodifiable( final IntCollection c ) { return new UnmodifiableCollection ( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection extends AbstractIntCollection implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntIterable iterable;
|
|
+ protected IterableCollection( final IntIterable iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final IntIterator iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public IntIterator iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public IntIterator intIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static IntCollection asCollection( final IntIterable iterable ) {
|
|
+ if ( iterable instanceof IntCollection ) return (IntCollection )iterable;
|
|
+ return new IterableCollection ( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Comparator;
|
|
+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
|
|
+ * and as primitive types.
|
|
+ *
|
|
+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
|
|
+ * can be used to implement this interface just by specifying the type-specific
|
|
+ * comparator.
|
|
+ *
|
|
+ * @see Comparator
|
|
+ */
|
|
+public interface IntComparator extends Comparator<Integer> {
|
|
+ /** Compares the given primitive types.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ * @return A positive integer, zero, or a negative integer if the first
|
|
+ * argument is greater than, equal to, or smaller than, respectively, the
|
|
+ * second one.
|
|
+ */
|
|
+ public int compare( int k1, int k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntComparators.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with comparators.
|
|
+ */
|
|
+public class IntComparators {
|
|
+ private IntComparators() {}
|
|
+ /** A type-specific comparator mimicking the natural order. */
|
|
+ protected static class NaturalImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return ( Integer.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return NATURAL_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final IntComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
|
|
+ /** A type-specific comparator mimicking the opposite of the natural order. */
|
|
+ protected static class OppositeImplicitComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return - ( Integer.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return OPPOSITE_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final IntComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
|
|
+ protected static class OppositeComparator extends AbstractIntComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final IntComparator comparator;
|
|
+ protected OppositeComparator( final IntComparator c ) {
|
|
+ comparator = c;
|
|
+ }
|
|
+ public final int compare( final int a, final int b ) {
|
|
+ return comparator.compare( b, a );
|
|
+ }
|
|
+ };
|
|
+ /** Returns a comparator representing the opposite order of the given comparator.
|
|
+ *
|
|
+ * @param c a comparator.
|
|
+ * @return a comparator representing the opposite order of <code>c</code>.
|
|
+ */
|
|
+ public static IntComparator oppositeComparator( final IntComparator c ) {
|
|
+ return new OppositeComparator ( c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHash.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+/** A type-specific {@link Hash} interface.
|
|
+ *
|
|
+ * @see Hash
|
|
+ */
|
|
+public interface IntHash {
|
|
+ /** A type-specific hash strategy.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Hash.Strategy
|
|
+ */
|
|
+ public interface Strategy {
|
|
+ /** Returns the hash code of the specified element with respect to this hash strategy.
|
|
+ *
|
|
+ * @param e an element.
|
|
+ * @return the hash code of the given element with respect to this hash strategy.
|
|
+ */
|
|
+ public int hashCode( int e );
|
|
+ /** Returns true if the given elements are equal with respect to this hash strategy.
|
|
+ *
|
|
+ * @param a an element.
|
|
+ * @param b another element.
|
|
+ * @return true if the two specified elements are equal with respect to this hash strategy.
|
|
+ */
|
|
+ public boolean equals( int a, int b );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapIndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific heap-based indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use an additional <em>inversion array</em>, of the same length of the reference array,
|
|
+ * to keep track of the heap position containing a given element of the reference array. The priority queue is
|
|
+ * represented using a heap. The heap is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation does <em>not</em> allow one to enqueue several times the same index.
|
|
+ */
|
|
+public class IntHeapIndirectPriorityQueue extends IntHeapSemiIndirectPriorityQueue {
|
|
+ /** The inversion array. */
|
|
+ protected final int inv[];
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ super( refArray, capacity, c );
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ this.inv = new int[ refArray.length ];
|
|
+ Arrays.fill( inv, -1 );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ int i = size;
|
|
+ while( i-- != 0 ) {
|
|
+ if ( inv[ a[ i ] ] != -1 ) throw new IllegalArgumentException( "Index " + a[ i ] + " appears twice in the heap" );
|
|
+ inv[ a[ i ] ] = i;
|
|
+ }
|
|
+ IntIndirectHeaps.makeHeap( refArray, a, inv, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntHeapIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ public void enqueue( final int x ) {
|
|
+ if ( inv[ x ] >= 0 ) throw new IllegalArgumentException( "Index " + x + " belongs to the queue" );
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ inv[ heap[ size ] = x ] = size++;
|
|
+ IntIndirectHeaps.upHeap( refArray, heap, inv, size, size - 1, c );
|
|
+ }
|
|
+ public boolean contains( final int index ) {
|
|
+ return inv[ index ] >= 0;
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ if ( --size != 0 ) inv[ heap[ 0 ] = heap[ size ] ] = 0;
|
|
+ inv[ result ] = -1;
|
|
+ if ( size != 0 ) IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public void changed() {
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, 0, c );
|
|
+ }
|
|
+ public void changed( final int index ) {
|
|
+ final int pos = inv[ index ];
|
|
+ if ( pos < 0 ) throw new IllegalArgumentException( "Index " + index + " does not belong to the queue" );
|
|
+ final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, pos, c );
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
|
|
+ }
|
|
+ /** Rebuilds this heap in a bottom-up fashion.
|
|
+ */
|
|
+ public void allChanged() {
|
|
+ IntIndirectHeaps.makeHeap( refArray, heap, inv, size, c );
|
|
+ }
|
|
+ public boolean remove( final int index ) {
|
|
+ final int result = inv[ index ];
|
|
+ if ( result < 0 ) return false;
|
|
+ inv[ index ] = -1;
|
|
+ if ( result < --size ) {
|
|
+ inv[ heap[ result ] = heap[ size ] ] = result;
|
|
+ final int newPos = IntIndirectHeaps.upHeap( refArray, heap, inv, size, result, c );
|
|
+ IntIndirectHeaps.downHeap( refArray, heap, inv, size, newPos, c );
|
|
+ }
|
|
+ return true;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ Arrays.fill( inv, -1 );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific heap-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a heap. The heap is enlarged as needed, but
|
|
+ * it is never shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ */
|
|
+public class IntHeapPriorityQueue extends AbstractIntPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The heap array. */
|
|
+
|
|
+ protected transient int[] heap = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public IntHeapPriorityQueue( int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( IntComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, int size, final IntComparator c ) {
|
|
+ this( c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ IntHeaps.makeHeap( a, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, final IntComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final int[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a type-specific collection using a given comparator.
|
|
+ *
|
|
+ * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final IntCollection collection, final IntComparator c ) {
|
|
+ this( collection.toIntArray(), c );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a type-specific collection using the natural order.
|
|
+ *
|
|
+ * <P>This constructor is
|
|
+ * more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final IntCollection collection ) {
|
|
+ this( collection, null );
|
|
+ }
|
|
+ /** Creates a queue using the elements in a collection using a given comparator.
|
|
+ *
|
|
+ * <P>This constructor is more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection, final IntComparator c ) {
|
|
+ this( collection.size(), c );
|
|
+ final Iterator<? extends Integer> iterator = collection.iterator();
|
|
+ final int size = collection.size();
|
|
+ for( int i = 0 ; i < size; i++ ) heap[ i ] = ((((Integer)(iterator.next())).intValue()));
|
|
+ }
|
|
+ /** Creates a queue using the elements in a collection using the natural order.
|
|
+ *
|
|
+ * <P>This constructor is
|
|
+ * more efficient than enqueing the elements of <code>collection</code> one by one.
|
|
+ *
|
|
+ * @param collection a collection; its elements will be used to initialize the queue.
|
|
+ */
|
|
+ public IntHeapPriorityQueue( final Collection<? extends Integer> collection ) {
|
|
+ this( collection, null );
|
|
+ }
|
|
+ public void enqueue( int x ) {
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ heap[ size++ ] = x;
|
|
+ IntHeaps.upHeap( heap, size, size - 1, c );
|
|
+ }
|
|
+ public int dequeueInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ heap[ 0 ] = heap[ --size ];
|
|
+ if ( size != 0 ) IntHeaps.downHeap( heap, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return heap[ 0 ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ IntHeaps.downHeap( heap, size, 0, c );
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ /** Trims the underlying heap array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ heap = IntArrays.trim( heap, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( heap.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeInt( heap[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ heap = new int[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) heap[ i ] = s.readInt();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeapSemiIndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import it.unimi.dsi.fastutil.AbstractIndirectPriorityQueue;
|
|
+/** A type-specific heap-based semi-indirect priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class use as reference list a <em>reference array</em>,
|
|
+ * which must be provided to each constructor. The priority queue is
|
|
+ * represented using a heap. The heap is enlarged as needed, but it is never
|
|
+ * shrunk. Use the {@link #trim()} method to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation allows one to enqueue several time the same index, but
|
|
+ * you must be careful when calling {@link #changed()}.
|
|
+ */
|
|
+public class IntHeapSemiIndirectPriorityQueue extends AbstractIndirectPriorityQueue<Integer> implements IntIndirectPriorityQueue {
|
|
+ /** The reference array. */
|
|
+ protected final int refArray[];
|
|
+ /** The semi-indirect heap. */
|
|
+ protected int heap[] = IntArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected IntComparator c;
|
|
+ /** Creates a new empty queue without elements with a given capacity and comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity, IntComparator c ) {
|
|
+ if ( capacity > 0 ) this.heap = new int[ capacity ];
|
|
+ this.refArray = refArray;
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with given capacity and using the natural order.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, int capacity ) {
|
|
+ this( refArray, capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and a given comparator.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( int[] refArray, IntComparator c ) {
|
|
+ this( refArray, refArray.length, c );
|
|
+ }
|
|
+ /** Creates a new empty queue with capacity equal to the length of the reference array and using the natural order.
|
|
+ * @param refArray the reference array.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray ) {
|
|
+ this( refArray, refArray.length, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size, final IntComparator c ) {
|
|
+ this( refArray, 0, c );
|
|
+ this.heap = a;
|
|
+ this.size = size;
|
|
+ IntSemiIndirectHeaps.makeHeap( refArray, a, size, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, final IntComparator c ) {
|
|
+ this( refArray, a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The first <code>size</code> element of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a, int size ) {
|
|
+ this( refArray, a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ * The elements of the array will be rearranged so to form a heap (this is
|
|
+ * more efficient than enqueing the elements of <code>a</code> one by one).
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param a an array of indices into <code>refArray</code>.
|
|
+ */
|
|
+ public IntHeapSemiIndirectPriorityQueue( final int[] refArray, final int[] a ) {
|
|
+ this( refArray, a, a.length );
|
|
+ }
|
|
+ /** Ensures that the given index is a valid reference.
|
|
+ *
|
|
+ * @param index an index in the reference array.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or larger than the reference array length.
|
|
+ */
|
|
+ protected void ensureElement( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= refArray.length ) throw new IndexOutOfBoundsException( "Index (" + index + ") is larger than or equal to reference array size (" + refArray.length + ")" );
|
|
+ }
|
|
+ public void enqueue( int x ) {
|
|
+ ensureElement( x );
|
|
+ if ( size == heap.length ) heap = IntArrays.grow( heap, size + 1 );
|
|
+ heap[ size++ ] = x;
|
|
+ IntSemiIndirectHeaps.upHeap( refArray, heap, size, size - 1, c );
|
|
+ }
|
|
+ public int dequeue() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int result = heap[ 0 ];
|
|
+ heap[ 0 ] = heap[ --size ];
|
|
+ if ( size != 0 ) IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
|
|
+ return result;
|
|
+ }
|
|
+ public int first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return heap[ 0 ];
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ *
|
|
+ * <P>The caller <strong>must</strong> guarantee that when this method is called the
|
|
+ * index of the first element appears just once in the queue. Failure to do so
|
|
+ * will bring the queue in an inconsistent state, and will cause
|
|
+ * unpredictable behaviour.
|
|
+ */
|
|
+ public void changed() {
|
|
+ IntSemiIndirectHeaps.downHeap( refArray, heap, size, 0, c );
|
|
+ }
|
|
+ /** Rebuilds this heap in a bottom-up fashion.
|
|
+ */
|
|
+ public void allChanged() {
|
|
+ IntSemiIndirectHeaps.makeHeap( refArray, heap, size, c );
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() { size = 0; }
|
|
+ /** Trims the backing array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ heap = IntArrays.trim( heap, size );
|
|
+ }
|
|
+ public IntComparator comparator() { return c; }
|
|
+ public int front( final int[] a ) {
|
|
+ return c == null ? IntSemiIndirectHeaps.front( refArray, heap, size, a ) : IntSemiIndirectHeaps.front( refArray, heap, size, a, c );
|
|
+ }
|
|
+ public String toString() {
|
|
+ StringBuffer s = new StringBuffer();
|
|
+ s.append( "[" );
|
|
+ for ( int i = 0; i < size; i++ ) {
|
|
+ if ( i != 0 ) s.append( ", " );
|
|
+ s.append( refArray[ heap [ i ] ] );
|
|
+ }
|
|
+ s.append( "]" );
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntHeaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with heaps.
|
|
+ *
|
|
+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
|
|
+ * are used in the implementation of heap-based queues, but they may be also used
|
|
+ * directly.
|
|
+ *
|
|
+ */
|
|
+public class IntHeaps {
|
|
+ private IntHeaps() {}
|
|
+ /** Moves the given element down into the heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
|
|
+ if ( ( (e) <= (t) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( e, t ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (t) <= (e) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( t, e ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Makes an array into a heap.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] heap, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( heap, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectHeaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Arrays;
|
|
+/** A class providing static methods and objects that do useful things with indirect heaps.
|
|
+ *
|
|
+ * <P>An indirect heap is an extension of a semi-indirect heap using also an
|
|
+ * <em>inversion array</em> of the same length as the reference array,
|
|
+ * satisfying the relation <code>heap[inv[i]]==i</code> when
|
|
+ * <code>inv[i]>=0</code>, and <code>inv[heap[i]]==i</code> for all elements in the heap.
|
|
+ */
|
|
+public class IntIndirectHeaps {
|
|
+ private IntIndirectHeaps() {}
|
|
+ /** Moves the given element down into the indirect heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the indirect heap (starting at 0).
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
|
|
+ if ( ( (E) <= (refArray[ t ]) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ inv[ e ] = i;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the indirect heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * Note that in principle after this call the heap property may be violated.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the indirect heap (starting at 0).
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (refArray[ t ]) <= (E) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( refArray[ t ], E ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ inv[ heap[ i ] ] = i;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ inv[ e ] = i;
|
|
+ return i;
|
|
+ }
|
|
+ /** Creates an indirect heap in the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param heap the array where the heap is to be created.
|
|
+ * @param inv the inversion array.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final int[] inv, final IntComparator c ) {
|
|
+ IntArrays.ensureOffsetLength( refArray, offset, length );
|
|
+ if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
|
|
+ if ( inv.length < refArray.length ) throw new IllegalArgumentException( "The inversion array length (" + heap.length + ") is smaller than the length of the reference array (" + refArray.length + ")" );
|
|
+ Arrays.fill( inv, 0, refArray.length, -1 );
|
|
+ int i = length;
|
|
+ while( i-- != 0 ) inv[ heap[ i ] = offset + i ] = i;
|
|
+ i = length >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, inv, length, i, c );
|
|
+ }
|
|
+ /** Creates an indirect heap from a given index array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param inv the inversion array.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int[] heap, final int[] inv, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, inv, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIndirectPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.IndirectPriorityQueue;
|
|
+/** A type-specific {@link IndirectPriorityQueue}.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface IntIndirectPriorityQueue extends IndirectPriorityQueue<Integer> {
|
|
+ /** Returns the comparator associated with this queue.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link IndirectPriorityQueue}.
|
|
+ *
|
|
+ * @return the comparator associated with this queue.
|
|
+ * @see IndirectPriorityQueue#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterable.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface IntIterator extends Iterator<Integer> {
|
|
+ /**
|
|
+ * Returns the next element as a primitive type.
|
|
+ *
|
|
+ * @return the next element in the iteration.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int nextInt();
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntIterators.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class IntIterators {
|
|
+ private IntIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator extends AbstractIntListIterator implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public int nextInt() { throw new NoSuchElementException(); }
|
|
+ public int previousInt() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator extends AbstractIntListIterator {
|
|
+ private final int element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static IntListIterator singleton( final int element ) {
|
|
+ return new SingletonIterator ( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator extends AbstractIntListIterator {
|
|
+ private final int[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final int[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static IntListIterator wrap( final int[] array, final int offset, final int length ) {
|
|
+ IntArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator ( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static IntListIterator wrap( final int[] array ) {
|
|
+ return new ArrayIterator ( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final int array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextInt();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final int array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+
|
|
+ public static int[] unwrap( final IntIterator i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int array[] = new int[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = IntArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.nextInt();
|
|
+ }
|
|
+ return IntArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static int[] unwrap( final IntIterator i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int unwrap( final IntIterator i, final IntCollection c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.nextInt() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static long unwrap( final IntIterator i, final IntCollection c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.nextInt() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final IntIterator i, final IntCollection s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.nextInt() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final IntIterator i, final IntCollection s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static IntList pour( final IntIterator i, int max ) {
|
|
+ final IntArrayList l = new IntArrayList ();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static IntList pour( final IntIterator i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper extends AbstractIntIterator {
|
|
+ final Iterator<Integer> i;
|
|
+ public IteratorWrapper( final Iterator<Integer> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public int nextInt() { return ((i.next()).intValue()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static IntIterator asIntIterator( final Iterator i ) {
|
|
+ if ( i instanceof IntIterator ) return (IntIterator )i;
|
|
+ return new IteratorWrapper ( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper extends AbstractIntListIterator {
|
|
+ final ListIterator<Integer> i;
|
|
+ public ListIteratorWrapper( final ListIterator<Integer> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( int k ) { i.set( (Integer.valueOf(k)) ); }
|
|
+ public void add( int k ) { i.add( (Integer.valueOf(k)) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public int nextInt() { return ((i.next()).intValue()); }
|
|
+ public int previousInt() { return ((i.previous()).intValue()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static IntListIterator asIntIterator( final ListIterator i ) {
|
|
+ if ( i instanceof IntListIterator ) return (IntListIterator )i;
|
|
+ return new ListIteratorWrapper ( i );
|
|
+ }
|
|
+ private static class IntervalIterator extends AbstractIntListIterator {
|
|
+ private final int from, to;
|
|
+ int curr;
|
|
+ public IntervalIterator( final int from, final int to ) {
|
|
+ this.from = this.curr = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < to; }
|
|
+ public boolean hasPrevious() { return curr > from; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return curr++;
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return --curr;
|
|
+ }
|
|
+ public int nextIndex() { return curr - from; }
|
|
+ public int previousIndex() { return curr - from - 1; }
|
|
+ public int skip( int n ) {
|
|
+ if ( curr + n <= to ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = to - curr;
|
|
+ curr = to;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( curr - n >= from ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr - from ;
|
|
+ curr = from;
|
|
+ return n;
|
|
+ }
|
|
+ }
|
|
+ /** Creates a type-specific list iterator over an interval.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return the
|
|
+ * elements <code>from</code>, <code>from+1</code>,…, <code>to-1</code>.
|
|
+ *
|
|
+ * @param from the starting element (inclusive).
|
|
+ * @param to the ending element (exclusive).
|
|
+ * @return a type-specific list iterator enumerating the elements from <code>from</code> to <code>to</code>.
|
|
+ */
|
|
+ public static IntListIterator fromTo( final int from, final int to ) {
|
|
+ return new IntervalIterator( from, to );
|
|
+ }
|
|
+ private static class IteratorConcatenator extends AbstractIntIterator {
|
|
+ final IntIterator a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final IntIterator a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ int next = a[ lastOffset = offset ].nextInt();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static IntIterator concat( final IntIterator a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static IntIterator concat( final IntIterator a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator ( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator extends AbstractIntIterator {
|
|
+ final protected IntIterator i;
|
|
+ public UnmodifiableIterator( final IntIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static IntIterator unmodifiable( final IntIterator i ) { return new UnmodifiableIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator extends AbstractIntBidirectionalIterator {
|
|
+ final protected IntBidirectionalIterator i;
|
|
+ public UnmodifiableBidirectionalIterator( final IntBidirectionalIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ public int previousInt() { return i.previousInt(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static IntBidirectionalIterator unmodifiable( final IntBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator extends AbstractIntListIterator {
|
|
+ final protected IntListIterator i;
|
|
+ public UnmodifiableListIterator( final IntListIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextInt() { return i.nextInt(); }
|
|
+ public int previousInt() { return i.previousInt(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Integer previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static IntListIterator unmodifiable( final IntListIterator i ) { return new UnmodifiableListIterator ( i ); }
|
|
+
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenCustomHashSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific linked hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
|
|
+ * have been added to the set (addition of elements already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted set, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first element
|
|
+ * in iteration order with {@code first()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
|
|
+ * contract because all subset methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by this class are type-specific {@linkplain
|
|
+ * java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is in the set</em> (if the provided element
|
|
+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
|
|
+ * If, however, the provided element is not the first or last element in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class IntLinkedOpenCustomHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The hash strategy of this custom set. */
|
|
+ protected it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Collection<? extends Integer> c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntCollection c, final float f, it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntCollection c, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntIterator i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f, strategy );
|
|
+ while( i.hasNext() ) add( i.nextInt() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final IntIterator i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( IntIterators.asIntIterator( i ), f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( IntIterators.asIntIterator( i ), strategy );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( length < 0 ? 0 : length, f, strategy );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final int offset, final int length, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final float f, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, 0, a.length, f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public IntLinkedOpenCustomHashSet( final int[] a, final it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash set.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.ints.IntHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ key[ n ] = k;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final int k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /** Removes the first key in iteration order.
|
|
+ * @return the first key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeFirstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ /** Removes the the last key in iteration order.
|
|
+ * @return the last key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeLastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToFirst( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ // There's always an unused entry. TODO
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToLast( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToLast( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (k), (key[ pos ]) ) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET(link[ d ], -1, -1)
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first element of this set in iteration order.
|
|
+ *
|
|
+ * @return the first element in iteration order.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last element of this set in iteration order.
|
|
+ *
|
|
+ * @return the last element in iteration order.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ /** A list iterator over a linked set.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time.
|
|
+ */
|
|
+ private class SetIterator extends AbstractIntListIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
|
|
+ int index = -1;
|
|
+ SetIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ SetIterator( int from ) {
|
|
+ if ( ( strategy.equals( (from), (0) ) ) ) {
|
|
+ if ( IntLinkedOpenCustomHashSet.this.containsNull ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ if ( ( strategy.equals( (key[ last ]), (from) ) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ final int key[] = IntLinkedOpenCustomHashSet.this.key;
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (key[ pos ]), (from) ) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ IntLinkedOpenCustomHashSet.this.containsNull = false;
|
|
+ IntLinkedOpenCustomHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = IntLinkedOpenCustomHashSet.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
|
|
+ * Please see the class documentation for implementation details.
|
|
+ *
|
|
+ * @param from an element to start from.
|
|
+ * @return a type-specific list iterator starting at the given element.
|
|
+ * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
|
|
+ */
|
|
+ public IntListIterator iterator( int from ) {
|
|
+ return new SetIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( strategy.equals( (key[ i ]), (0) ) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenCustomHashSet clone() {
|
|
+ IntLinkedOpenCustomHashSet c;
|
|
+ try {
|
|
+ c = (IntLinkedOpenCustomHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.link = link.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += ( strategy.hashCode(key[ i ]) );
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final IntIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLinkedOpenHashSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific linked hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this set will enumerate elements in the same order in which they
|
|
+ * have been added to the set (addition of elements already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted set, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first element
|
|
+ * in iteration order with {@code first()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedSet}
|
|
+ * contract because all subset methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>addAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by this class are type-specific {@linkplain
|
|
+ * java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is in the set</em> (if the provided element
|
|
+ * is not in the set, a {@link NoSuchElementException} exception will be thrown).
|
|
+ * If, however, the provided element is not the first or last element in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting element. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class IntLinkedOpenHashSet extends AbstractIntSortedSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient int[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenHashSet( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new int[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Collection<? extends Integer> c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntCollection c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntCollection c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntIterator i, final float f ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f );
|
|
+ while( i.hasNext() ) add( i.nextInt() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final IntIterator i ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Iterator<?> i, final float f ) {
|
|
+ this( IntIterators.asIntIterator( i ), f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final Iterator<?> i ) {
|
|
+ this( IntIterators.asIntIterator( i ) );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length, final float f ) {
|
|
+ this( length < 0 ? 0 : length, f );
|
|
+ IntArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final int offset, final int length ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a, final float f ) {
|
|
+ this( a, 0, a.length, f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ */
|
|
+ public IntLinkedOpenHashSet( final int[] a ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( IntCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Integer> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER(link[ pos ], -1, -1);
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final int k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNull;
|
|
+ int curr;
|
|
+ final int[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /** Removes the first key in iteration order.
|
|
+ * @return the first key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeFirstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ /** Removes the the last key in iteration order.
|
|
+ * @return the last key.
|
|
+ * @throws NoSuchElementException is this set is empty.
|
|
+ */
|
|
+ public int removeLastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ final int k = key[ pos ];
|
|
+ size--;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return k;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToFirst( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ // There's always an unused entry. TODO
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (k) == (key[ pos ]) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Adds a key to the set; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return true if the key was not present.
|
|
+ */
|
|
+ public boolean addAndMoveToLast( final int k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) {
|
|
+ moveIndexToLast( n );
|
|
+ return false;
|
|
+ }
|
|
+ containsNull = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ // The starting point.
|
|
+ final int key[] = this.key;
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (k) == (key[ pos ]) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return false;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET(link[ d ], -1, -1)
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first element of this set in iteration order.
|
|
+ *
|
|
+ * @return the first element in iteration order.
|
|
+ */
|
|
+ public int firstInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last element of this set in iteration order.
|
|
+ *
|
|
+ * @return the last element in iteration order.
|
|
+ */
|
|
+ public int lastInt() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public IntSortedSet tailSet( int from ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet headSet( int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntSortedSet subSet( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ /** A list iterator over a linked set.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash set. The constructor runs in constant time.
|
|
+ */
|
|
+ private class SetIterator extends AbstractIntListIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link #remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). When -1, we do not know the current index.*/
|
|
+ int index = -1;
|
|
+ SetIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ SetIterator( int from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( IntLinkedOpenHashSet.this.containsNull ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ final int key[] = IntLinkedOpenHashSet.this.key;
|
|
+ int pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (from) ) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this set." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ public int nextInt() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ if ( ASSERTS ) assert curr == n || ! ( (key[ curr ]) == (0) ) : "Position " + curr + " is not used";
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ public int previousInt() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return key[ curr ];
|
|
+ }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ IntLinkedOpenHashSet.this.containsNull = false;
|
|
+ IntLinkedOpenHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else {
|
|
+ int curr;
|
|
+ final int[] key = IntLinkedOpenHashSet.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific list iterator on the elements in this set, starting from a given element of the set.
|
|
+ * Please see the class documentation for implementation details.
|
|
+ *
|
|
+ * @param from an element to start from.
|
|
+ * @return a type-specific list iterator starting at the given element.
|
|
+ * @throws IllegalArgumentException if <code>from</code> does not belong to the set.
|
|
+ */
|
|
+ public IntListIterator iterator( int from ) {
|
|
+ return new SetIterator( from );
|
|
+ }
|
|
+ public IntListIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final int key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final int newKey[] = new int[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public IntLinkedOpenHashSet clone() {
|
|
+ IntLinkedOpenHashSet c;
|
|
+ try {
|
|
+ c = (IntLinkedOpenHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += (key[ i ]);
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final IntIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeInt( i.nextInt() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final int key[] = this.key = new int[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ int k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readInt();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( (k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface IntList extends List<Integer>, Comparable<List<? extends Integer>>, IntCollection {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ IntListIterator iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntListIterator intListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntListIterator intListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ IntListIterator listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ IntListIterator listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntList intSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ IntList subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, int a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, int a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, int a[], int offset, int length );
|
|
+ /**
|
|
+ * @see List#add(Object)
|
|
+ */
|
|
+ boolean add( int key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ void add( int index, int key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, IntCollection c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, IntList c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( IntList c );
|
|
+ /**
|
|
+ * @see List#get(int)
|
|
+ */
|
|
+ int getInt( int index );
|
|
+ /**
|
|
+ * @see List#indexOf(Object)
|
|
+ */
|
|
+ int indexOf( int k );
|
|
+ /**
|
|
+ * @see List#lastIndexOf(Object)
|
|
+ */
|
|
+ int lastIndexOf( int k );
|
|
+ /**
|
|
+ * @see List#remove(int)
|
|
+ */
|
|
+ int removeInt( int index );
|
|
+ /**
|
|
+ * @see List#set(int,Object)
|
|
+ */
|
|
+ int set( int index, int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface IntListIterator extends ListIterator<Integer>, IntBidirectionalIterator {
|
|
+ void set( int k );
|
|
+ void add( int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntLists.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.List;
|
|
+import java.util.Collection;
|
|
+import java.util.Random;
|
|
+/** A class providing static methods and objects that do useful things with type-specific lists.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntLists {
|
|
+ private IntLists() {}
|
|
+ /** Shuffles the specified list using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param l the list to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>l</code>.
|
|
+ */
|
|
+ public static IntList shuffle( final IntList l, final Random random ) {
|
|
+ for( int i = l.size(); i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final int t = l.getInt( i );
|
|
+ l.set( i, l.getInt( p ) );
|
|
+ l.set( p, t );
|
|
+ }
|
|
+ return l;
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class EmptyList extends IntCollections.EmptyCollection implements IntList , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyList() {}
|
|
+ public void add( final int index, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int removeInt( int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int set( final int index, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( int k ) { return -1; }
|
|
+ public int lastIndexOf( int k ) { return -1; }
|
|
+ public boolean addAll( Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer get( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public boolean addAll( IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( IntList c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, IntList c ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer set( final int index, final Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public int getInt( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public Integer remove( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( Object k ) { return -1; }
|
|
+ public int lastIndexOf( Object k ) { return -1; }
|
|
+ //SUPPRESS_WARNINGS_KEY_UNCHECKED
|
|
+ //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+
|
|
+ public IntIterator intIterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator listIterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator iterator() { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntListIterator listIterator( int i ) { if ( i == 0 ) return IntIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( int i ) { return listIterator( i ); }
|
|
+ public IntList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( int from, int to ) { return subList( from, to ); }
|
|
+ public void getElements( int from, int[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
|
|
+ public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( int s ) { throw new UnsupportedOperationException(); }
|
|
+ public int compareTo( final List<? extends Integer> o ) {
|
|
+ if ( o == this ) return 0;
|
|
+ return ((List<?>)o).isEmpty() ? 0 : -1;
|
|
+ }
|
|
+ private Object readResolve() { return EMPTY_LIST; }
|
|
+ public Object clone() { return EMPTY_LIST; }
|
|
+ public int hashCode() { return 1; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
|
|
+ public String toString() { return "[]"; }
|
|
+ }
|
|
+ /** An empty list (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptyList EMPTY_LIST = new EmptyList();
|
|
+ /** An immutable class representing a type-specific singleton list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class Singleton extends AbstractIntList implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private final int element;
|
|
+ private Singleton( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public int getInt( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
|
|
+ public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final int k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final Collection <? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public int[] toIntArray() {
|
|
+ int a[] = new int[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public IntListIterator listIterator() { return IntIterators.singleton( element ); }
|
|
+ public IntListIterator iterator() { return listIterator(); }
|
|
+ public IntListIterator listIterator( int i ) {
|
|
+ if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
|
|
+ IntListIterator l = listIterator();
|
|
+ if ( i == 1 ) l.next();
|
|
+ return l;
|
|
+ }
|
|
+
|
|
+ public IntList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( from != 0 || to != 1 ) return EMPTY_LIST;
|
|
+ return this;
|
|
+ }
|
|
+ public int size() { return 1; }
|
|
+ public void size( final int size ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return this; }
|
|
+ public boolean rem( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntList singleton( final int element ) { return new Singleton ( element ); }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntList singleton( final Object element ) { return new Singleton ( ((((Integer)(element)).intValue())) ); }
|
|
+ /** A synchronized wrapper class for lists. */
|
|
+ public static class SynchronizedList extends IntCollections.SynchronizedCollection implements IntList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected SynchronizedList( final IntList l, final Object sync ) {
|
|
+ super( l, sync );
|
|
+ this.list = l;
|
|
+ }
|
|
+ protected SynchronizedList( final IntList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public int getInt( final int i ) { synchronized( sync ) { return list.getInt( i ); } }
|
|
+ public int set( final int i, final int k ) { synchronized( sync ) { return list.set( i, k ); } }
|
|
+ public void add( final int i, final int k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public int removeInt( final int i ) { synchronized( sync ) { return list.removeInt( i ); } }
|
|
+ public int indexOf( final int k ) { synchronized( sync ) { return list.indexOf( k ); } }
|
|
+ public int lastIndexOf( final int k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public void getElements( final int from, final int a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
|
|
+ public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
|
|
+ public void addElements( int index, final int a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
|
|
+ public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
|
|
+ public IntListIterator iterator() { return list.listIterator(); }
|
|
+ public IntListIterator listIterator() { return list.listIterator(); }
|
|
+ public IntListIterator listIterator( final int i ) { return list.listIterator( i ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
|
|
+ public IntList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ public int compareTo( final List<? extends Integer> o ) { synchronized( sync ) { return list.compareTo( o ); } }
|
|
+ public boolean addAll( final int index, final IntCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public boolean addAll( final int index, IntList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
|
|
+ public boolean addAll( IntList l ) { synchronized( sync ) { return list.addAll( l ); } }
|
|
+ public Integer get( final int i ) { synchronized( sync ) { return list.get( i ); } }
|
|
+ public void add( final int i, Integer k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public Integer set( final int index, Integer k ) { synchronized( sync ) { return list.set( index, k ); } }
|
|
+ public Integer remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
|
|
+ public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
|
|
+ public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static IntList synchronize( final IntList l ) { return new SynchronizedList ( l ); }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @param sync an object that will be used to synchronize the access to the list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static IntList synchronize( final IntList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
|
|
+ /** An unmodifiable wrapper class for lists. */
|
|
+ public static class UnmodifiableList extends IntCollections.UnmodifiableCollection implements IntList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected UnmodifiableList( final IntList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public int getInt( final int i ) { return list.getInt( i ); }
|
|
+ public int set( final int i, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int i, final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int removeInt( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final int k ) { return list.indexOf( k ); }
|
|
+ public int lastIndexOf( final int k ) { return list.lastIndexOf( k ); }
|
|
+ public boolean addAll( final int index, final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void getElements( final int from, final int a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
|
|
+ public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final int a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( final int size ) { list.size( size ); }
|
|
+ public IntListIterator iterator() { return listIterator(); }
|
|
+ public IntListIterator listIterator() { return IntIterators.unmodifiable( list.listIterator() ); }
|
|
+ public IntListIterator listIterator( final int i ) { return IntIterators.unmodifiable( list.listIterator( i ) ); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public IntListIterator intListIterator( final int i ) { return listIterator( i ); }
|
|
+ public IntList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
|
|
+ @Deprecated
|
|
+ public IntList intSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ public int compareTo( final List<? extends Integer> o ) { return list.compareTo( o ); }
|
|
+ public boolean addAll( final int index, final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final IntList l ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int index, final IntList l ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer get( final int i ) { return list.get( i ); }
|
|
+ public void add( final int i, Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer set( final int index, Integer k ) { throw new UnsupportedOperationException(); }
|
|
+ public Integer remove( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final Object o ) { return list.indexOf( o ); }
|
|
+ public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in an unmodifiable list.
|
|
+ * @return an unmodifiable view of the specified list.
|
|
+ * @see java.util.Collections#unmodifiableList(List)
|
|
+ */
|
|
+ public static IntList unmodifiable( final IntList l ) { return new UnmodifiableList ( l ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface IntPriorityQueue extends PriorityQueue<Integer> {
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue.
|
|
+ */
|
|
+ void enqueue( int x );
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int dequeueInt();
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int firstInt();
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ int lastInt();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
|
|
+ *
|
|
+ * @see PriorityQueue#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntPriorityQueues.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+/** A class providing static methods and objects that do useful things with type-specific priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+public class IntPriorityQueues {
|
|
+ private IntPriorityQueues() {}
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+ public static class SynchronizedPriorityQueue implements IntPriorityQueue {
|
|
+ final protected IntPriorityQueue q;
|
|
+ final protected Object sync;
|
|
+ protected SynchronizedPriorityQueue( final IntPriorityQueue q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedPriorityQueue( final IntPriorityQueue q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public void enqueue( int x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public int dequeueInt() { synchronized( sync ) { return q.dequeueInt(); } }
|
|
+ public int firstInt() { synchronized( sync ) { return q.firstInt(); } }
|
|
+ public int lastInt() { synchronized( sync ) { return q.lastInt(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public IntComparator comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public void enqueue( Integer x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public Integer dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public Integer first() { synchronized( sync ) { return q.first(); } }
|
|
+ public Integer last() { synchronized( sync ) { return q.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static IntPriorityQueue synchronize( final IntPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static IntPriorityQueue synchronize( final IntPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSemiIndirectHeaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+/** A class providing static methods and objects that do useful things with semi-indirect heaps.
|
|
+ *
|
|
+ * <P>A semi-indirect heap is based on a <em>reference array</em>. Elements of
|
|
+ * a semi-indirect heap are integers that index the reference array (note that
|
|
+ * in an <em>indirect</em> heap you can also map elements of the reference
|
|
+ * array to heap positions).
|
|
+ */
|
|
+public class IntSemiIndirectHeaps {
|
|
+ private IntSemiIndirectHeaps() {}
|
|
+ /** Moves the given element down into the semi-indirect heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the semi-indirect heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (refArray[ heap[ right ] ]) < (refArray[ t ]) ) ) t = heap[ child = right ];
|
|
+ if ( ( (E) <= (refArray[ t ]) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ int t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( refArray[ heap[ right ] ], refArray[ t ] ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( E, refArray[ t ] ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the semi-indirect heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap the semi-indirect heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index in the heap of the element to be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position in the heap of the element of heap index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final int[] refArray, final int[] heap, final int size, int i, final IntComparator c ) {
|
|
+ assert i < size;
|
|
+ final int e = heap[ i ];
|
|
+ final int E = refArray[ e ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( ( (refArray[ t ]) <= (E) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final int t = heap[ parent ];
|
|
+ if ( c.compare( refArray[ t ], E ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Creates a semi-indirect heap in the given array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param heap the array where the heap is to be created.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int offset, final int length, final int[] heap, final IntComparator c ) {
|
|
+ IntArrays.ensureOffsetLength( refArray, offset, length );
|
|
+ if ( heap.length < length ) throw new IllegalArgumentException( "The heap length (" + heap.length + ") is smaller than the number of elements (" + length + ")" );
|
|
+ int i = length;
|
|
+ while( i-- != 0 ) heap[ i ] = offset + i;
|
|
+ i = length >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, length, i, c );
|
|
+ }
|
|
+ /** Creates a semi-indirect heap, allocating its heap array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param offset the first element of the reference array to be put in the heap.
|
|
+ * @param length the number of elements to be put in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the heap array.
|
|
+ */
|
|
+ public static int[] makeHeap( final int[] refArray, final int offset, final int length, final IntComparator c ) {
|
|
+ final int[] heap = length <= 0 ? IntArrays.EMPTY_ARRAY : new int[ length ];
|
|
+ makeHeap( refArray, offset, length, heap, c );
|
|
+ return heap;
|
|
+ }
|
|
+ /** Creates a semi-indirect heap from a given index array.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final int[] refArray, final int[] heap, final int size, final IntComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( refArray, heap, size, i, c );
|
|
+ }
|
|
+ /** Retrieves the front of a heap in a given array.
|
|
+ *
|
|
+ * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the first index.
|
|
+ *
|
|
+ * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
|
|
+ * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that
|
|
+ * terminates when all visited nodes are larger than the element associated
|
|
+ * to the top index, which implies that no elements of the front can be found later.
|
|
+ * In most cases this trick yields a significant improvement.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+
|
|
+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a ) {
|
|
+ final int top = refArray[ heap[ 0 ] ];
|
|
+ int j = 0, // The current position in a
|
|
+ l = 0, // The first position to visit in the next level (inclusive)
|
|
+ r = 1, // The last position to visit in the next level (exclusive)
|
|
+ f = 0; // The first position (in the heap array) of the next level
|
|
+ for( int i = 0; i < r; i++ ) {
|
|
+ if ( i == f ) { // New level
|
|
+ if ( l >= r ) break; // If we are crossing the two bounds, we're over
|
|
+ f = (f << 1) + 1; // Update the first position of the next level...
|
|
+ i = l; // ...and jump directly to position l
|
|
+ l = -1; // Invalidate l
|
|
+ }
|
|
+ if ( ( (top) == (refArray[ heap[ i ] ]) ) ) {
|
|
+ a[ j++ ] = heap[ i ];
|
|
+ if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
|
|
+ r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
|
|
+ }
|
|
+ }
|
|
+ return j;
|
|
+ }
|
|
+ /** Retrieves the front of a heap in a given array using a given comparator.
|
|
+ *
|
|
+ * <p>The <em>front</em> of a semi-indirect heap is the set of indices whose associated elements in the reference array
|
|
+ * are equal to the element associated to the first index.
|
|
+ *
|
|
+ * <p>In several circumstances you need to know the front, and scanning linearly the entire heap is not
|
|
+ * the best strategy. This method simulates (using a partial linear scan) a breadth-first visit that
|
|
+ * terminates when all visited nodes are larger than the element associated
|
|
+ * to the top index, which implies that no elements of the front can be found later.
|
|
+ * In most cases this trick yields a significant improvement.
|
|
+ *
|
|
+ * @param refArray the reference array.
|
|
+ * @param heap an array containing indices into <code>refArray</code>.
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param a an array large enough to hold the front (e.g., at least long as <code>refArray</code>).
|
|
+ * @param c a type-specific comparator.
|
|
+ * @return the number of elements actually written (starting from the first position of <code>a</code>).
|
|
+ */
|
|
+ public static int front( final int[] refArray, final int[] heap, final int size, final int[] a, final IntComparator c ) {
|
|
+ final int top = refArray[ heap[ 0 ] ];
|
|
+ int j = 0, // The current position in a
|
|
+ l = 0, // The first position to visit in the next level (inclusive)
|
|
+ r = 1, // The last position to visit in the next level (exclusive)
|
|
+ f = 0; // The first position (in the heap array) of the next level
|
|
+ for( int i = 0; i < r; i++ ) {
|
|
+ if ( i == f ) { // New level
|
|
+ if ( l >= r ) break; // If we are crossing the two bounds, we're over
|
|
+ f = (f << 1) + 1; // Update the first position of the next level...
|
|
+ i = l; // ...and jump directly to position l
|
|
+ l = -1; // Invalidate l
|
|
+ }
|
|
+ if ( c.compare( top, refArray[ heap[ i ] ] ) == 0 ) {
|
|
+ a[ j++ ] = heap[ i ];
|
|
+ if ( l == -1 ) l = i * 2 + 1; // If this is the first time in this level, set l
|
|
+ r = Math.min( size, i * 2 + 3 ); // Update r, but do not go beyond size
|
|
+ }
|
|
+ }
|
|
+ return j;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface IntSet extends IntCollection , Set<Integer> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ IntIterator iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( int k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntSets {
|
|
+ private IntSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet extends IntCollections.EmptyCollection implements IntSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton extends AbstractIntSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final int element;
|
|
+ protected Singleton( final int element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final int k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Integer> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public int[] toIntArray() {
|
|
+ int a[] = new int[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final IntCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public IntListIterator iterator() { return IntIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSet singleton( final int element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSet singleton( final Integer element ) {
|
|
+ return new Singleton ( ((element).intValue()) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet extends IntCollections.SynchronizedCollection implements IntSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final IntSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final IntSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final int k ) { synchronized( sync ) { return collection.remove( (Integer.valueOf(k)) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static IntSet synchronize( final IntSet s ) { return new SynchronizedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static IntSet synchronize( final IntSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet extends IntCollections.UnmodifiableCollection implements IntSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final IntSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final int k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static IntSet unmodifiable( final IntSet s ) { return new UnmodifiableSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface IntSortedSet extends IntSet , SortedSet<Integer> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ IntBidirectionalIterator iterator( int fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ IntBidirectionalIterator intIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ IntBidirectionalIterator iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ IntSortedSet subSet( Integer fromElement, Integer toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ IntSortedSet headSet( Integer toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ IntSortedSet tailSet( Integer fromElement );
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
|
|
+ *
|
|
+ * @see SortedSet#comparator()
|
|
+ */
|
|
+ IntComparator comparator();
|
|
+ /**
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ IntSortedSet subSet( int fromElement, int toElement) ;
|
|
+ /**
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ IntSortedSet headSet( int toElement );
|
|
+ /**
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ IntSortedSet tailSet( int fromElement );
|
|
+ /**
|
|
+ * @see SortedSet#first()
|
|
+ */
|
|
+ int firstInt();
|
|
+ /**
|
|
+ * @see SortedSet#last()
|
|
+ */
|
|
+ int lastInt();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntSortedSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class IntSortedSets {
|
|
+ private IntSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet extends IntSets.EmptySet implements IntSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( int ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return iterator(); }
|
|
+
|
|
+ public IntBidirectionalIterator iterator( int from ) { return IntIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public IntSortedSet subSet( int from, int to ) { return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet headSet( int from ) { return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet tailSet( int to ) { return EMPTY_SET; }
|
|
+ public int firstInt() { throw new NoSuchElementException(); }
|
|
+ public int lastInt() { throw new NoSuchElementException(); }
|
|
+ public IntComparator comparator() { return null; }
|
|
+ public IntSortedSet subSet( Integer from, Integer to ) { return EMPTY_SET; }
|
|
+ public IntSortedSet headSet( Integer from ) { return EMPTY_SET; }
|
|
+ public IntSortedSet tailSet( Integer to ) { return EMPTY_SET; }
|
|
+ public Integer first() { throw new NoSuchElementException(); }
|
|
+ public Integer last() { throw new NoSuchElementException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton extends IntSets.Singleton implements IntSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final IntComparator comparator;
|
|
+ private Singleton( final int element, final IntComparator comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final int element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final int k1, final int k2 ) {
|
|
+ return comparator == null ? ( Integer.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public IntBidirectionalIterator iterator( int from ) {
|
|
+ IntBidirectionalIterator i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public IntComparator comparator() { return comparator; }
|
|
+
|
|
+ public IntSortedSet subSet( final int from, final int to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet headSet( final int to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public IntSortedSet tailSet( final int from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public int firstInt() { return element; }
|
|
+ public int lastInt() { return element; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer first() { return (Integer.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Integer last() { return (Integer.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return subSet( ((from).intValue()), ((to).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet headSet( final Integer to ) { return headSet( ((to).intValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public IntSortedSet tailSet( final Integer from ) { return tailSet( ((from).intValue()) ); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final int element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final int element, final IntComparator comparator ) {
|
|
+ return new Singleton ( element, comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final Object element ) {
|
|
+ return new Singleton( ((((Integer)(element)).intValue())) );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static IntSortedSet singleton( final Object element, final IntComparator comparator ) {
|
|
+ return new Singleton( ((((Integer)(element)).intValue())), comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet extends IntSets.SynchronizedSet implements IntSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntSortedSet sortedSet;
|
|
+ protected SynchronizedSortedSet( final IntSortedSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final IntSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public IntComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
|
|
+ public IntSortedSet headSet( final int to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
|
|
+ public IntSortedSet tailSet( final int from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
|
|
+ public IntBidirectionalIterator iterator() { return sortedSet.iterator(); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return sortedSet.iterator(); }
|
|
+ public int firstInt() { synchronized( sync ) { return sortedSet.firstInt(); } }
|
|
+ public int lastInt() { synchronized( sync ) { return sortedSet.lastInt(); } }
|
|
+ public Integer first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public Integer last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
|
|
+ public IntSortedSet headSet( final Integer to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
|
|
+ public IntSortedSet tailSet( final Integer from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet synchronize( final IntSortedSet s ) { return new SynchronizedSortedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet synchronize( final IntSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet extends IntSets.UnmodifiableSet implements IntSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final IntSortedSet sortedSet;
|
|
+ protected UnmodifiableSortedSet( final IntSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public IntComparator comparator() { return sortedSet.comparator(); }
|
|
+ public IntSortedSet subSet( final int from, final int to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
|
|
+ public IntSortedSet headSet( final int to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
|
|
+ public IntSortedSet tailSet( final int from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
|
|
+ public IntBidirectionalIterator iterator() { return IntIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public IntBidirectionalIterator iterator( final int from ) { return IntIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public IntBidirectionalIterator intIterator() { return iterator(); }
|
|
+ public int firstInt() { return sortedSet.firstInt(); }
|
|
+ public int lastInt() { return sortedSet.lastInt(); }
|
|
+ public Integer first() { return sortedSet.first(); }
|
|
+ public Integer last() { return sortedSet.last(); }
|
|
+ public IntSortedSet subSet( final Integer from, final Integer to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
|
|
+ public IntSortedSet headSet( final Integer to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
|
|
+ public IntSortedSet tailSet( final Integer from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static IntSortedSet unmodifiable( final IntSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/IntStack.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.ints;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ */
|
|
+public interface IntStack extends Stack<Integer> {
|
|
+ /**
|
|
+ * @see Stack#push(Object)
|
|
+ */
|
|
+ void push( int k );
|
|
+ /**
|
|
+ * @see Stack#pop()
|
|
+ */
|
|
+ int popInt();
|
|
+ /**
|
|
+ * @see Stack#top()
|
|
+ */
|
|
+ int topInt();
|
|
+ /**
|
|
+ * @see Stack#peek(int)
|
|
+ */
|
|
+ int peekInt( int i );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/ints/package.html b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/ints/package.html
|
|
@@ -0,0 +0,0 @@
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
+<html>
|
|
+ <head>
|
|
+ <title>fastutil</title>
|
|
+ </head>
|
|
+
|
|
+ <body>
|
|
+
|
|
+ <P>Provides type-specific classes for integer elements or keys.
|
|
+
|
|
+ </body>
|
|
+</html>
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectFunction.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class providing basic methods for functions implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>This class handles directly a default return
|
|
+ * value (including {@linkplain #defaultReturnValue() methods to access
|
|
+ * it}). Instances of classes inheriting from this class have just to return
|
|
+ * <code>defRetValue</code> to denote lack of a key in type-specific methods. The value
|
|
+ * is serialized.
|
|
+ *
|
|
+ * <P>Implementing subclasses have just to provide type-specific <code>get()</code>,
|
|
+ * type-specific <code>containsKey()</code>, and <code>size()</code> methods.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractLong2ObjectFunction <V> implements Long2ObjectFunction <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractLong2ObjectFunction() {}
|
|
+ /**
|
|
+ * The default return value for <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code>.
|
|
+ */
|
|
+ protected V defRetValue;
|
|
+ public void defaultReturnValue( final V rv ) {
|
|
+ defRetValue = rv;
|
|
+ }
|
|
+ public V defaultReturnValue() {
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public V put( long key, V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public V remove( long key ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public void clear() {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean containsKey( final Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return containsKey( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V get( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ return containsKey( k ) ? (get( k )) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ *
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final long k = ((ok).longValue());
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = put( k, (ov) );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method, taking care of returning <code>null</code> on a missing key.
|
|
+ *
|
|
+ * <P>This method must check whether the provided key is in the map using <code>containsKey()</code>. Thus,
|
|
+ * it probes the map <em>twice</em>. Implementors of subclasses should override it with a more efficient method.
|
|
+ */
|
|
+ public V remove( final Object ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ final boolean containsKey = containsKey( k );
|
|
+ final V v = remove( k );
|
|
+ return containsKey ? (v) : null;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import java.util.Iterator;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for maps implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>Optional operations just throw an {@link
|
|
+ * UnsupportedOperationException}. Generic versions of accessors delegate to
|
|
+ * the corresponding type-specific counterparts following the interface rules
|
|
+ * (they take care of returning <code>null</code> on a missing key).
|
|
+ *
|
|
+ * <P>As a further help, this class provides a {@link BasicEntry BasicEntry} inner class
|
|
+ * that implements a type-specific version of {@link java.util.Map.Entry}; it
|
|
+ * is particularly useful for those classes that do not implement their own
|
|
+ * entries (e.g., most immutable maps).
|
|
+ */
|
|
+public abstract class AbstractLong2ObjectMap <V> extends AbstractLong2ObjectFunction <V> implements Long2ObjectMap <V>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -4940583368468432370L;
|
|
+ protected AbstractLong2ObjectMap() {}
|
|
+ /** Checks whether the given value is contained in {@link #values()}. */
|
|
+ public boolean containsValue( Object v ) {
|
|
+ return values().contains( v );
|
|
+ }
|
|
+ /** Checks whether the given value is contained in {@link #keySet()}. */
|
|
+ public boolean containsKey( long k ) {
|
|
+ return keySet().contains( k );
|
|
+ }
|
|
+ /** Puts all pairs in the given map.
|
|
+ * If the map implements the interface of this map,
|
|
+ * it uses the faster iterators.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","deprecation"})
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ int n = m.size();
|
|
+ final Iterator<? extends Map.Entry<? extends Long,? extends V>> i = m.entrySet().iterator();
|
|
+ if (m instanceof Long2ObjectMap) {
|
|
+ Long2ObjectMap.Entry <? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = (Long2ObjectMap.Entry <? extends V>)i.next();
|
|
+ put(e.getLongKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ Map.Entry<? extends Long,? extends V> e;
|
|
+ while(n-- != 0) {
|
|
+ e = i.next();
|
|
+ put(e.getKey(), e.getValue());
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ /** This class provides a basic but complete type-specific entry class for all those maps implementations
|
|
+ * that do not have entries on their own (e.g., most immutable maps).
|
|
+ *
|
|
+ * <P>This class does not implement {@link java.util.Map.Entry#setValue(Object) setValue()}, as the modification
|
|
+ * would not be reflected in the base map.
|
|
+ */
|
|
+ public static class BasicEntry <V> implements Long2ObjectMap.Entry <V> {
|
|
+ protected long key;
|
|
+ protected V value;
|
|
+ public BasicEntry( final Long key, final V value ) {
|
|
+ this.key = ((key).longValue());
|
|
+ this.value = (value);
|
|
+ }
|
|
+ public BasicEntry( final long key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key;
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value);
|
|
+ }
|
|
+ public V setValue( final V value ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (key) == (((((Long)(e.getKey())).longValue()))) ) && ( (value) == null ? ((e.getValue())) == null : (value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key + "->" + value;
|
|
+ }
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public LongSet keySet() {
|
|
+ return new AbstractLongSet () {
|
|
+ public boolean contains( final long k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractLong2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectMap.this.clear(); }
|
|
+ public LongIterator iterator() {
|
|
+ return new AbstractLongIterator () {
|
|
+ final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public long nextLong() { return ((Long2ObjectMap.Entry <V>)i.next()).getLongKey(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** Returns a type-specific-set view of the values of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a set view of the values of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new AbstractObjectCollection <V>() {
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractLong2ObjectMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectMap.this.clear(); }
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new AbstractObjectIterator <V>() {
|
|
+ final ObjectIterator<Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V next() { return ((Long2ObjectMap.Entry <V>)i.next()).getValue(); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ };
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() {
|
|
+ return (ObjectSet)long2ObjectEntrySet();
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * The hash code of a map is computed by summing the hash codes of its entries.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ while( n-- != 0 ) h += i.next().hashCode();
|
|
+ return h;
|
|
+ }
|
|
+ public boolean equals(Object o) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != size() ) return false;
|
|
+ return entrySet().containsAll( m.entrySet() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator<? extends Map.Entry<Long,V>> i = entrySet().iterator();
|
|
+ int n = size();
|
|
+ Long2ObjectMap.Entry <V> e;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ e = (Long2ObjectMap.Entry <V>)i.next();
|
|
+ s.append(String.valueOf(e.getLongKey()));
|
|
+ s.append("=>");
|
|
+ if (this == e.getValue()) s.append("(this map)"); else
|
|
+ s.append(String.valueOf(e.getValue()));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLong2ObjectSortedMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import java.util.Map;
|
|
+/** An abstract class providing basic methods for sorted maps implementing a type-specific interface. */
|
|
+public abstract class AbstractLong2ObjectSortedMap <V> extends AbstractLong2ObjectMap <V> implements Long2ObjectSortedMap <V> {
|
|
+ private static final long serialVersionUID = -1773560792952436569L;
|
|
+ protected AbstractLong2ObjectSortedMap() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( final Long to ) {
|
|
+ return headMap( ((to).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( final Long from ) {
|
|
+ return tailMap( ((from).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( final Long from, final Long to ) {
|
|
+ return subMap( ((from).longValue()), ((to).longValue()) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() {
|
|
+ return (Long.valueOf(firstLongKey()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() {
|
|
+ return (Long.valueOf(lastLongKey()));
|
|
+ }
|
|
+ /** Returns a type-specific-sorted-set view of the keys of this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a sorted set view of the keys of this map; it may be safely cast to a type-specific interface.
|
|
+ */
|
|
+ public LongSortedSet keySet() {
|
|
+ return new KeySet();
|
|
+ }
|
|
+ /** A wrapper exhibiting the keys of a map. */
|
|
+ protected class KeySet extends AbstractLongSortedSet {
|
|
+ public boolean contains( final long k ) { return containsKey( k ); }
|
|
+ public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
|
|
+ public LongComparator comparator() { return AbstractLong2ObjectSortedMap.this.comparator(); }
|
|
+ public long firstLong() { return firstLongKey(); }
|
|
+ public long lastLong() { return lastLongKey(); }
|
|
+ public LongSortedSet headSet( final long to ) { return headMap( to ).keySet(); }
|
|
+ public LongSortedSet tailSet( final long from ) { return tailMap( from ).keySet(); }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return subMap( from, to ).keySet(); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return new KeySetIterator <V>( entrySet().iterator( new BasicEntry <V>( from, (null) ) ) ); }
|
|
+ public LongBidirectionalIterator iterator() { return new KeySetIterator <V>( entrySet().iterator() ); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on keys.
|
|
+ *
|
|
+ * <P>To provide an iterator on keys, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class KeySetIterator <V> extends AbstractLongBidirectionalIterator {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
|
|
+ public KeySetIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public long nextLong() { return ((i.next().getKey()).longValue()); };
|
|
+ public long previousLong() { return ((i.previous().getKey()).longValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ }
|
|
+ /** Returns a type-specific collection view of the values contained in this map.
|
|
+ *
|
|
+ * <P>The view is backed by the sorted set returned by {@link #entrySet()}. Note that
|
|
+ * <em>no attempt is made at caching the result of this method</em>, as this would
|
|
+ * require adding some attributes that lightweight implementations would
|
|
+ * not need. Subclasses may easily override this policy by calling
|
|
+ * this method and caching the result, but implementors are encouraged to
|
|
+ * write more efficient ad-hoc implementations.
|
|
+ *
|
|
+ * @return a type-specific collection view of the values contained in this map.
|
|
+ */
|
|
+ public ObjectCollection <V> values() {
|
|
+ return new ValuesCollection();
|
|
+ }
|
|
+ /** A wrapper exhibiting the values of a map. */
|
|
+ protected class ValuesCollection extends AbstractObjectCollection <V> {
|
|
+ public ObjectIterator <V> iterator() { return new ValuesIterator <V>( entrySet().iterator() ); }
|
|
+ public boolean contains( final Object k ) { return containsValue( k ); }
|
|
+ public int size() { return AbstractLong2ObjectSortedMap.this.size(); }
|
|
+ public void clear() { AbstractLong2ObjectSortedMap.this.clear(); }
|
|
+ }
|
|
+ /** A wrapper exhibiting a map iterator as an iterator on values.
|
|
+ *
|
|
+ * <P>To provide an iterator on values, just create an instance of this
|
|
+ * class using the corresponding iterator on entries.
|
|
+ */
|
|
+ protected static class ValuesIterator <V> extends AbstractObjectIterator <V> {
|
|
+ protected final ObjectBidirectionalIterator<Map.Entry <Long, V>> i;
|
|
+ public ValuesIterator( ObjectBidirectionalIterator<Map.Entry <Long, V>> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public V next() { return (i.next().getValue()); };
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ }
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() {
|
|
+ return (ObjectSortedSet)long2ObjectEntrySet();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractLongBidirectionalIterator extends AbstractLongIterator implements LongBidirectionalIterator {
|
|
+ protected AbstractLongBidirectionalIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public long previousLong() { return previous().longValue(); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public Long previous() { return Long.valueOf( previousLong() ); }
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousLong();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractLongCollection extends AbstractCollection<Long> implements LongCollection {
|
|
+ protected AbstractLongCollection() {}
|
|
+ public long[] toArray( long a[] ) {
|
|
+ return toLongArray( a );
|
|
+ }
|
|
+ public long[] toLongArray() {
|
|
+ return toLongArray( null );
|
|
+ }
|
|
+ public long[] toLongArray( long a[] ) {
|
|
+ if ( a == null || a.length < size() ) a = new long[ size() ];
|
|
+ LongIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given type-specific collection to this collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ final LongIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.nextLong() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( LongCollection c ) {
|
|
+ final LongIterator i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( ! contains( i.nextLong() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final LongIterator i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.nextLong() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( LongCollection c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final LongIterator i = c.iterator();
|
|
+ while( n-- != 0 ) if ( rem( i.nextLong() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends Long> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract LongIterator iterator();
|
|
+ /** Delegates to the type-specific <code>rem()</code> method. */
|
|
+ public boolean remove( Object ok ) {
|
|
+ if ( ok == null ) return false;
|
|
+ return rem( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean add( final Long o ) {
|
|
+ return add( o.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean rem( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( o == null ) return false;
|
|
+ return contains( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ final LongIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() ) if ( k == iterator.nextLong() ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ public boolean rem( final long k ) {
|
|
+ final LongIterator iterator = iterator();
|
|
+ while ( iterator.hasNext() )
|
|
+ if ( k == iterator.nextLong() ) {
|
|
+ iterator.remove();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final LongIterator i = iterator();
|
|
+ int n = size();
|
|
+ long k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextLong();
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongComparator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.Comparator comparators}.
|
|
+ *
|
|
+ * <P>To create a type-specific comparator you need both a method comparing
|
|
+ * primitive types and a method comparing objects. However, if you have the
|
|
+ * first one you can just inherit from this class and get for free the second
|
|
+ * one.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ */
|
|
+public abstract class AbstractLongComparator implements LongComparator , java.io.Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ protected AbstractLongComparator() {}
|
|
+ public int compare( Long ok1, Long ok2 ) {
|
|
+ return compare( ok1.longValue(), ok2.longValue() );
|
|
+ }
|
|
+ public abstract int compare( long k1, long k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractLongIterator implements LongIterator {
|
|
+ protected AbstractLongIterator() {}
|
|
+ /** Delegates to the corresponding generic method. */
|
|
+ public long nextLong() { return next().longValue(); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long next() { return Long.valueOf( nextLong() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextLong();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractLongList extends AbstractLongCollection implements LongList , LongStack {
|
|
+ protected AbstractLongList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public long removeLong( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public long set( final int index, final long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends Long> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends Long> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends Long> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public LongListIterator iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public LongListIterator listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractLongList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = pos++ ); }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractLongList.this.getLong( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ AbstractLongList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractLongList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractLongList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final long k ) {
|
|
+ final LongListIterator i = listIterator();
|
|
+ long e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.nextLong();
|
|
+ if ( ( (k) == (e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final long k ) {
|
|
+ LongListIterator i = listIterator( size() );
|
|
+ long e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previousLong();
|
|
+ if ( ( (k) == (e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (0) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new LongSubList ( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ LongListIterator i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.nextLong();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final long a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final long a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final long a[], int offset, int length ) {
|
|
+ LongListIterator i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.nextLong();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ if ( l instanceof LongList ) {
|
|
+ final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
|
|
+ while( s-- != 0 ) if ( i1.nextLong() != i2.nextLong() ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final List<? extends Long> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof LongList ) {
|
|
+ final LongListIterator i1 = listIterator(), i2 = ((LongList )l).listIterator();
|
|
+ int r;
|
|
+ long e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.nextLong();
|
|
+ e2 = i2.nextLong();
|
|
+ if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends Long> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super Long>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ LongIterator i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ long k = i.nextLong();
|
|
+ h = 31 * h + it.unimi.dsi.fastutil.HashCommon.long2int(k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( long o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public long popLong() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return removeLong( size() - 1 );
|
|
+ }
|
|
+ public long topLong() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return getLong( size() - 1 );
|
|
+ }
|
|
+ public long peekLong( int i ) {
|
|
+ return getLong( size() - 1 - i );
|
|
+ }
|
|
+ public boolean rem( long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeLong( index );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to <code>rem()</code>. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final LongCollection c ) {
|
|
+ return addAll( index, (Collection<? extends Long>)c );
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ return addAll( index, (LongCollection)l );
|
|
+ }
|
|
+ public boolean addAll( final LongCollection c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ public boolean addAll( final LongList l ) {
|
|
+ return addAll( size(), l );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( final int index, final Long ok ) {
|
|
+ add( index, ok.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long set( final int index, final Long ok ) {
|
|
+ return (Long.valueOf(set( index, ok.longValue() )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long get( final int index ) {
|
|
+ return (Long.valueOf(getLong( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int indexOf( final Object ok) {
|
|
+ return indexOf( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public int lastIndexOf( final Object ok ) {
|
|
+ return lastIndexOf( ((((Long)(ok)).longValue())) );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long remove( final int index ) {
|
|
+ return (Long.valueOf(removeLong( index )));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void push( Long o ) {
|
|
+ push( o.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long pop() {
|
|
+ return Long.valueOf( popLong() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long top() {
|
|
+ return Long.valueOf( topLong() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long peek( int i ) {
|
|
+ return Long.valueOf( peekLong( i ) );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final LongIterator i = iterator();
|
|
+ int n = size();
|
|
+ long k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.nextLong();
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class LongSubList extends AbstractLongList implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final LongList l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public LongSubList( final LongList l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public long getLong( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.getLong( from + index );
|
|
+ }
|
|
+ public long removeLong( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.removeLong( from + index );
|
|
+ }
|
|
+ public long set( int index, long k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final long[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.getLong( from + ( last = pos++ ) ); }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.getLong( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongSubList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new LongSubList ( this, from, to );
|
|
+ }
|
|
+ public boolean rem( long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ to--;
|
|
+ l.removeLong( from + index );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ ensureIndex( index );
|
|
+ to += l.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = this.l.addAll( from + index, l );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return this.l.addAll( from + index, l );
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractLongListIterator extends AbstractLongBidirectionalIterator implements LongListIterator {
|
|
+ protected AbstractLongListIterator() {}
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void set( Long ok ) { set( ok.longValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public void add( Long ok ) { add( ok.longValue() ); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( long k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( long k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.AbstractPriorityQueue;
|
|
+/** An abstract class providing basic methods for priority queues implementing a type-specific interface.
|
|
+ *
|
|
+ */
|
|
+public abstract class AbstractLongPriorityQueue extends AbstractPriorityQueue<Long> implements java.io.Serializable, LongPriorityQueue {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public void enqueue( final Long x ) { enqueue( x.longValue() ); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long dequeue() { return (Long.valueOf(dequeueLong())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() { return (Long.valueOf(firstLong())); }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() { return (Long.valueOf(lastLong())); }
|
|
+ /** Throws an {@link UnsupportedOperationException}. */
|
|
+ public long lastLong() { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractLongSet extends AbstractLongCollection implements Cloneable, LongSet {
|
|
+ protected AbstractLongSet() {}
|
|
+ public abstract LongIterator iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ LongIterator i = iterator();
|
|
+ long k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.nextLong(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += it.unimi.dsi.fastutil.HashCommon.long2int(k);
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to <code>remove()</code>.
|
|
+ *
|
|
+ * @param k the element to be removed.
|
|
+ * @return true if the set was modified.
|
|
+ */
|
|
+ public boolean rem( long k ) {
|
|
+ return remove( k );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method. */
|
|
+ public boolean remove( final Object o ) {
|
|
+ return remove( ((((Long)(o)).longValue())) );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/AbstractLongSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractLongSortedSet extends AbstractLongSet implements LongSortedSet {
|
|
+ protected AbstractLongSortedSet() {}
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet headSet( final Long to ) {
|
|
+ return headSet( to.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet tailSet( final Long from ) {
|
|
+ return tailSet( from.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) {
|
|
+ return subSet( from.longValue(), to.longValue() );
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() {
|
|
+ return (Long.valueOf(firstLong()));
|
|
+ }
|
|
+ /** Delegates to the corresponding type-specific method.
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() {
|
|
+ return (Long.valueOf(lastLong()));
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract LongBidirectionalIterator iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectArrayMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Map;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A simple, brute-force implementation of a map based on two parallel backing arrays.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of pairs: just put them into two parallel arrays and scan linearly to find an item.
|
|
+ */
|
|
+public class Long2ObjectArrayMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The keys (valid up to {@link #size}, excluded). */
|
|
+ private transient long[] key;
|
|
+ /** The values (parallel to {@link #key}). */
|
|
+ private transient Object[] value;
|
|
+ /** The number of valid entries in {@link #key} and {@link #value}. */
|
|
+ private int size;
|
|
+ /** Creates a new empty array map with given key and value backing arrays. The resulting map will have as many entries as the given arrays.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final long[] key, final Object[] value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ size = key.length;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ }
|
|
+ /** Creates a new empty array map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap() {
|
|
+ this.key = LongArrays.EMPTY_ARRAY;
|
|
+ this.value = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array map of given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final int capacity ) {
|
|
+ this.key = new long[ capacity ];
|
|
+ this.value = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new empty array map copying the entries of a given map.
|
|
+ *
|
|
+ * @param m a map.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m.size() );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new array map with given key and value backing arrays, using the given number of elements.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>key</code> are distinct.
|
|
+ *
|
|
+ * @param key the key array.
|
|
+ * @param value the value array (it <em>must</em> have the same length as <code>key</code>).
|
|
+ * @param size the number of valid elements in <code>key</code> and <code>value</code>.
|
|
+ */
|
|
+ public Long2ObjectArrayMap( final long[] key, final Object[] value, final int size ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ this.size = size;
|
|
+ if( key.length != value.length ) throw new IllegalArgumentException( "Keys and values have different lengths (" + key.length + ", " + value.length + ")" );
|
|
+ if ( size > key.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the backing-arrays size (" + key.length + ")" );
|
|
+ }
|
|
+ private final class EntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ @Override
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
|
|
+ int curr = -1, next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return new AbstractLong2ObjectMap.BasicEntry <V>( key[ curr = next ], (V) value[ next++ ] );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new AbstractObjectIterator<Long2ObjectMap.Entry <V> >() {
|
|
+ int next = 0, curr = -1;
|
|
+ final BasicEntry <V> entry = new BasicEntry <V> ( (0), (null) );
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Entry <V> next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ entry.key = key[ curr = next ];
|
|
+ entry.value = (V) value[ next++ ];
|
|
+ return entry;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ curr = -1;
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( key, next + 1, key, next, tail );
|
|
+ System.arraycopy( value, next + 1, value, next, tail );
|
|
+ value[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( Object o ) {
|
|
+ if ( ! ( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ return Long2ObjectArrayMap.this.containsKey( k ) && ( (Long2ObjectArrayMap.this.get( k )) == null ? ((e.getValue())) == null : (Long2ObjectArrayMap.this.get( k )).equals((e.getValue())) );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ @Override
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ final int oldPos = Long2ObjectArrayMap.this.findKey( k );
|
|
+ if ( oldPos == -1 || ! ( (v) == null ? (Long2ObjectArrayMap.this.value[ oldPos ]) == null : (v).equals(Long2ObjectArrayMap.this.value[ oldPos ]) ) ) return false;
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( Long2ObjectArrayMap.this.key, oldPos + 1, Long2ObjectArrayMap.this.key, oldPos, tail );
|
|
+ System.arraycopy( Long2ObjectArrayMap.this.value, oldPos + 1, Long2ObjectArrayMap.this.value, oldPos, tail );
|
|
+ Long2ObjectArrayMap.this.size--;
|
|
+ Long2ObjectArrayMap.this.value[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ return new EntrySet();
|
|
+ }
|
|
+ private int findKey( final long k ) {
|
|
+ final long[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V get( final long k ) {
|
|
+ final long[] key = this.key;
|
|
+ for( int i = size; i-- != 0; ) if ( ( (key[ i ]) == (k) ) ) return (V) value[ i ];
|
|
+ return defRetValue;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ value[ i ] = null;
|
|
+ }
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsKey( final long k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean containsValue( Object v ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V put( long k, V v ) {
|
|
+ final int oldKey = findKey( k );
|
|
+ if ( oldKey != -1 ) {
|
|
+ final V oldValue = (V) value[ oldKey ];
|
|
+ value[ oldKey ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ if ( size == key.length ) {
|
|
+ final long[] newKey = new long[ size == 0 ? 2 : size * 2 ];
|
|
+ final Object[] newValue = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) {
|
|
+ newKey[ i ] = key[ i ];
|
|
+ newValue[ i ] = value[ i ];
|
|
+ }
|
|
+ key = newKey;
|
|
+ value = newValue;
|
|
+ }
|
|
+ key[ size ] = k;
|
|
+ value[ size ] = v;
|
|
+ size++;
|
|
+ return defRetValue;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public V remove( final long k ) {
|
|
+ final int oldPos = findKey( k );
|
|
+ if ( oldPos == -1 ) return defRetValue;
|
|
+ final V oldValue = (V) value[ oldPos ];
|
|
+ final int tail = size - oldPos - 1;
|
|
+ System.arraycopy( key, oldPos + 1, key, oldPos, tail );
|
|
+ System.arraycopy( value, oldPos + 1, value, oldPos, tail );
|
|
+ size--;
|
|
+ value[ size ] = null;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @Override
|
|
+ public LongSet keySet() {
|
|
+ return new LongArraySet ( key, size );
|
|
+ }
|
|
+ @Override
|
|
+ public ObjectCollection <V> values() {
|
|
+ return ObjectCollections.unmodifiable( new ObjectArraySet <V>( value, size ) );
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectArrayMap <V> clone() {
|
|
+ Long2ObjectArrayMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectArrayMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ s.writeLong( key[ i ] );
|
|
+ s.writeObject( value[ i ] );
|
|
+ }
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ key = new long[ size ];
|
|
+ value = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) {
|
|
+ key[ i ] = s.readLong();
|
|
+ value[ i ] = s.readObject();
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunction.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Function;
|
|
+/** A type-specific {@link Function}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Type-specific versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> cannot rely on <code>null</code> to denote absence of
|
|
+ * a key. Rather, they return a {@linkplain #defaultReturnValue() default
|
|
+ * return value}, which is set to 0 cast to the return type (<code>false</code>
|
|
+ * for booleans) at creation, but can be changed using the
|
|
+ * <code>defaultReturnValue()</code> method.
|
|
+ *
|
|
+ * <P>For uniformity reasons, even maps returning objects implement the default
|
|
+ * return value (of course, in this case the default return value is
|
|
+ * initialized to <code>null</code>).
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> to fall in line as much as possible with the
|
|
+ * {@linkplain java.util.Map standard map interface}, it is strongly suggested
|
|
+ * that standard versions of <code>get()</code>, <code>put()</code> and
|
|
+ * <code>remove()</code> for maps with primitive-type values <em>return
|
|
+ * <code>null</code> to denote missing keys</em> rather than wrap the default
|
|
+ * return value in an object (of course, for maps with object keys and values
|
|
+ * this is not possible, as there is no type-specific version).
|
|
+ *
|
|
+ * @see Function
|
|
+ */
|
|
+public interface Long2ObjectFunction <V> extends Function<Long, V> {
|
|
+ /** Adds a pair to the map.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @param value the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#put(Object,Object)
|
|
+ */
|
|
+ V put( long key, V value );
|
|
+ /** Returns the value to which the given key is mapped.
|
|
+ *
|
|
+ * @param key the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#get(Object)
|
|
+ */
|
|
+ V get( long key );
|
|
+ /** Removes the mapping with the given key.
|
|
+ * @param key the key.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ * @see Function#remove(Object)
|
|
+ */
|
|
+ V remove( long key );
|
|
+ /**
|
|
+ * @see Function#containsKey(Object)
|
|
+ */
|
|
+ boolean containsKey( long key );
|
|
+ /** Sets the default return value.
|
|
+ *
|
|
+ * This value must be returned by type-specific versions of
|
|
+ * <code>get()</code>, <code>put()</code> and <code>remove()</code> to
|
|
+ * denote that the map does not contain the specified key. It must be
|
|
+ * 0/<code>false</code>/<code>null</code> by default.
|
|
+ *
|
|
+ * @param rv the new default return value.
|
|
+ * @see #defaultReturnValue()
|
|
+ */
|
|
+ void defaultReturnValue( V rv );
|
|
+ /** Gets the default return value.
|
|
+ *
|
|
+ * @return the current default return value.
|
|
+ */
|
|
+ V defaultReturnValue();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectFunctions.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with type-specific functions.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Function
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectFunctions {
|
|
+ private Long2ObjectFunctions() {}
|
|
+ /** An immutable class representing an empty type-specific function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class EmptyFunction <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyFunction() {}
|
|
+ public V get( final long k ) { return (null); }
|
|
+ public boolean containsKey( final long k ) { return false; }
|
|
+ public V defaultReturnValue() { return (null); }
|
|
+ public void defaultReturnValue( final V defRetValue ) { throw new UnsupportedOperationException(); }
|
|
+ @Override
|
|
+ public V get( final Object k ) { return null; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ private Object readResolve() { return EMPTY_FUNCTION; }
|
|
+ public Object clone() { return EMPTY_FUNCTION; }
|
|
+ }
|
|
+ /** An empty type-specific function (immutable). It is serializable and cloneable. */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyFunction EMPTY_FUNCTION = new EmptyFunction();
|
|
+ /** An immutable class representing a type-specific singleton function.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific function.
|
|
+ */
|
|
+ public static class Singleton <V> extends AbstractLong2ObjectFunction <V> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final long key;
|
|
+ protected final V value;
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+ public boolean containsKey( final long k ) { return ( (key) == (k) ); }
|
|
+ public V get( final long k ) { if ( ( (key) == (k) ) ) return value; return defRetValue; }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable function containing only the specified pair. The returned function is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned function is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned function.
|
|
+ * @param value the only value of the returned function.
|
|
+ * @return a type-specific immutable function containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Comparator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+/** A type-specific linked hash map with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * <P>Iterators generated by this map will enumerate pairs in the same order in which they
|
|
+ * have been added to the map (addition of pairs whose key is already present
|
|
+ * in the set does not change the iteration order). Note that this order has nothing in common with the natural
|
|
+ * order of the keys. The order is kept by means of a doubly linked list, represented
|
|
+ * <i>via</i> an array of longs parallel to the table.
|
|
+ *
|
|
+ * <P>This class implements the interface of a sorted map, so to allow easy
|
|
+ * access of the iteration order: for instance, you can get the first key
|
|
+ * in iteration order with {@code firstKey()} without having to create an
|
|
+ * iterator; however, this class partially violates the {@link java.util.SortedMap}
|
|
+ * contract because all submap methods throw an exception and {@link
|
|
+ * #comparator()} returns always <code>null</code>.
|
|
+ *
|
|
+ * <p>Additional methods, such as <code>getAndMoveToFirst()</code>, make it easy
|
|
+ * to use instances of this class as a cache (e.g., with LRU policy).
|
|
+ *
|
|
+ * <P>The iterators provided by the views of this class using are type-specific
|
|
+ * {@linkplain java.util.ListIterator list iterators}, and can be started at any
|
|
+ * element <em>which is a key of the map</em>, or
|
|
+ * a {@link NoSuchElementException} exception will be thrown.
|
|
+ * If, however, the provided element is not the first or last key in the
|
|
+ * set, the first access to the list index will require linear time, as in the worst case
|
|
+ * the entire key set must be scanned in iteration order to retrieve the positional
|
|
+ * index of the starting key. If you use just the methods of a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator},
|
|
+ * however, all operations will be performed in constant time.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectLinkedOpenHashMap <V> extends AbstractLong2ObjectSortedMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The index of the first entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int first = -1;
|
|
+ /** The index of the last entry in iteration order. It is valid iff {@link #size} is nonzero; otherwise, it contains -1. */
|
|
+ protected transient int last = -1;
|
|
+ /** For each entry, the next and the previous entry in iteration order,
|
|
+ * stored as <code>((prev & 0xFFFFFFFFL) << 32) | (next & 0xFFFFFFFFL)</code>.
|
|
+ * The first entry contains predecessor -1, and the last entry
|
|
+ * contains successor -1. */
|
|
+ protected transient long[] link;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastSortedEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSortedSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectLinkedOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ link = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectLinkedOpenHashMap( final long[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ fixPointers( pos );
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ fixPointers( n );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ private V setValue( final int pos, final V v ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** Removes the mapping associated with the first key in iteration order.
|
|
+ * @return the value previously associated with the first key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeFirst() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = first;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ first = (int) link[ pos ];
|
|
+ if ( 0 <= first ) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ /** Removes the mapping associated with the last key in iteration order.
|
|
+ * @return the value previously associated with the last key in iteration order.
|
|
+ * @throws NoSuchElementException is this map is empty.
|
|
+ */
|
|
+ public V removeLast() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ final int pos = last;
|
|
+ // Abbreviated version of fixPointers(pos)
|
|
+ last = (int) ( link[ pos ] >>> 32 );
|
|
+ if ( 0 <= last ) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ size--;
|
|
+ final V v = value[ pos ];
|
|
+ if ( pos == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return v;
|
|
+ }
|
|
+ private void moveIndexToFirst( final int i ) {
|
|
+ if ( size == 1 || first == i ) return;
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ // Special case of SET_NEXT( link[ last ], -1 );
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( i & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ i ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = i;
|
|
+ }
|
|
+ private void moveIndexToLast( final int i ) {
|
|
+ if ( size == 1 || last == i ) return;
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ // Special case of SET_PREV( link[ first ], -1 );
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ else {
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( i & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ i ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = i;
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToFirst( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Returns the value to which the given key is mapped; if the key is present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @return the corresponding value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V getAndMoveToLast( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return value[ n ];
|
|
+ }
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the first position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToFirst( final long k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToFirst( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToFirst( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ first ] ^= ( ( link[ first ] ^ ( ( pos & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ pos ] = ( ( -1 & 0xFFFFFFFFL ) << 32 ) | ( first & 0xFFFFFFFFL );
|
|
+ first = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** Adds a pair to the map; if the key is already present, it is moved to the last position of the iteration order.
|
|
+ *
|
|
+ * @param k the key.
|
|
+ * @param v the value.
|
|
+ * @return the old value, or the {@linkplain #defaultReturnValue() default return value} if no value was present for the given key.
|
|
+ */
|
|
+ public V putAndMoveToLast( final long k, final V v ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) {
|
|
+ moveIndexToLast( n );
|
|
+ return setValue( n, v );
|
|
+ }
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ moveIndexToLast( pos );
|
|
+ return setValue( pos, v );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size == 0 ) {
|
|
+ first = last = pos;
|
|
+ // Special case of SET_UPPER_LOWER( link[ pos ], -1, -1 );
|
|
+ link[ pos ] = -1L;
|
|
+ }
|
|
+ else {
|
|
+ link[ last ] ^= ( ( link[ last ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] = ( ( last & 0xFFFFFFFFL ) << 32 ) | ( -1 & 0xFFFFFFFFL );
|
|
+ last = pos;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ first = last = -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector so that the given entry is removed.
|
|
+ * This method will complete in constant time.
|
|
+ *
|
|
+ * @param i the index of an entry.
|
|
+ */
|
|
+ protected void fixPointers( final int i ) {
|
|
+ if ( size == 0 ) {
|
|
+ first = last = -1;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == i ) {
|
|
+ first = (int) link[ i ];
|
|
+ if (0 <= first) {
|
|
+ // Special case of SET_PREV( link[ first ], -1 )
|
|
+ link[ first ] |= (-1 & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ if ( last == i ) {
|
|
+ last = (int) ( link[ i ] >>> 32 );
|
|
+ if (0 <= last) {
|
|
+ // Special case of SET_NEXT( link[ last ], -1 )
|
|
+ link[ last ] |= -1 & 0xFFFFFFFFL;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ final long linki = link[ i ];
|
|
+ final int prev = (int) ( linki >>> 32 );
|
|
+ final int next = (int) linki;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( linki & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( linki & 0xFFFFFFFF00000000L ) ) & 0xFFFFFFFF00000000L );
|
|
+ }
|
|
+ /** Modifies the {@link #link} vector for a shift from s to d.
|
|
+ * <P>This method will complete in constant time.
|
|
+ *
|
|
+ * @param s the source position.
|
|
+ * @param d the destination position.
|
|
+ */
|
|
+ protected void fixPointers( int s, int d ) {
|
|
+ if ( size == 1 ) {
|
|
+ first = last = d;
|
|
+ // Special case of SET_UPPER_LOWER( link[ d ], -1, -1 )
|
|
+ link[ d ] = -1L;
|
|
+ return;
|
|
+ }
|
|
+ if ( first == s ) {
|
|
+ first = d;
|
|
+ link[ (int) link[ s ] ] ^= ( ( link[ (int) link[ s ] ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ if ( last == s ) {
|
|
+ last = d;
|
|
+ link[ (int) ( link[ s ] >>> 32 )] ^= ( ( link[ (int) ( link[ s ] >>> 32 )] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ d ] = link[ s ];
|
|
+ return;
|
|
+ }
|
|
+ final long links = link[ s ];
|
|
+ final int prev = (int) ( links >>> 32 );
|
|
+ final int next = (int) links;
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( d & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( d & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ link[ d ] = links;
|
|
+ }
|
|
+ /** Returns the first key of this map in iteration order.
|
|
+ *
|
|
+ * @return the first key in iteration order.
|
|
+ */
|
|
+ public long firstLongKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ /** Returns the last key of this map in iteration order.
|
|
+ *
|
|
+ * @return the last key in iteration order.
|
|
+ */
|
|
+ public long lastLongKey() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ public Long2ObjectSortedMap <V> tailMap( long from ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectSortedMap <V> headMap( long to ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectSortedMap <V> subMap( long from, long to ) { throw new UnsupportedOperationException(); }
|
|
+ /** A list iterator over a linked map.
|
|
+ *
|
|
+ * <P>This class provides a list iterator over a linked hash map. The constructor runs in constant time.
|
|
+ */
|
|
+ private class MapIterator {
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#previous()} (or <code>null</code> if no previous entry exists). */
|
|
+ int prev = -1;
|
|
+ /** The entry that will be returned by the next call to {@link java.util.ListIterator#next()} (or <code>null</code> if no next entry exists). */
|
|
+ int next = -1;
|
|
+ /** The last entry that was returned (or -1 if we did not iterate or used {@link java.util.Iterator#remove()}). */
|
|
+ int curr = -1;
|
|
+ /** The current index (in the sense of a {@link java.util.ListIterator}). Note that this value is not meaningful when this iterator has been created using the nonempty constructor.*/
|
|
+ int index = -1;
|
|
+ private MapIterator() {
|
|
+ next = first;
|
|
+ index = 0;
|
|
+ }
|
|
+ private MapIterator( final long from ) {
|
|
+ if ( ( (from) == (0) ) ) {
|
|
+ if ( Long2ObjectLinkedOpenHashMap.this.containsNullKey ) {
|
|
+ next = (int) link[ n ];
|
|
+ prev = n;
|
|
+ return;
|
|
+ }
|
|
+ else throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ if ( ( (key[ last ]) == (from) ) ) {
|
|
+ prev = last;
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ // The starting point.
|
|
+ int pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (from) ) & mask;
|
|
+ // There's always an unused entry.
|
|
+ while( ! ( (key[ pos ]) == (0) ) ) {
|
|
+ if ( ( (key[ pos ]) == (from) ) ) {
|
|
+ // Note: no valid index known.
|
|
+ next = (int) link[ pos ];
|
|
+ prev = pos;
|
|
+ return;
|
|
+ }
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ throw new NoSuchElementException( "The key " + from + " does not belong to this map." );
|
|
+ }
|
|
+ public boolean hasNext() { return next != -1; }
|
|
+ public boolean hasPrevious() { return prev != -1; }
|
|
+ private final void ensureIndexKnown() {
|
|
+ if ( index >= 0 ) return;
|
|
+ if ( prev == -1 ) {
|
|
+ index = 0;
|
|
+ return;
|
|
+ }
|
|
+ if ( next == -1 ) {
|
|
+ index = size;
|
|
+ return;
|
|
+ }
|
|
+ int pos = first;
|
|
+ index = 1;
|
|
+ while( pos != prev ) {
|
|
+ pos = (int) link[ pos ];
|
|
+ index++;
|
|
+ }
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ ensureIndexKnown();
|
|
+ return index - 1;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = next;
|
|
+ next = (int) link[ curr ];
|
|
+ prev = curr;
|
|
+ if ( index >= 0 ) index++;
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousEntry() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = prev;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ next = curr;
|
|
+ if ( index >= 0 ) index--;
|
|
+ return curr;
|
|
+ }
|
|
+ public void remove() {
|
|
+ ensureIndexKnown();
|
|
+ if ( curr == -1 ) throw new IllegalStateException();
|
|
+ if ( curr == prev ) {
|
|
+ /* If the last operation was a next(), we are removing an entry that preceeds
|
|
+ the current index, and thus we must decrement it. */
|
|
+ index--;
|
|
+ prev = (int) ( link[ curr ] >>> 32 );
|
|
+ }
|
|
+ else
|
|
+ next = (int) link[ curr ];
|
|
+ size--;
|
|
+ /* Now we manually fix the pointers. Because of our knowledge of next
|
|
+ and prev, this is going to be faster than calling fixPointers(). */
|
|
+ if ( prev == -1 ) first = next;
|
|
+ else
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( next & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ if ( next == -1 ) last = prev;
|
|
+ else
|
|
+ link[ next ] ^= ( ( link[ next ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ int last, slot, pos = curr;
|
|
+ curr = -1;
|
|
+ if ( pos == n ) {
|
|
+ Long2ObjectLinkedOpenHashMap.this.containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ // We have to horribly duplicate the shiftKeys() code because we need to update next/prev.
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ if ( next == pos ) next = last;
|
|
+ if ( prev == pos ) prev = last;
|
|
+ fixPointers( pos, last );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previousEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public EntryIterator() {}
|
|
+ public EntryIterator( long from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ return entry = new MapEntry( previousEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectListIterator<Long2ObjectMap.Entry <V> > {
|
|
+ final MapEntry entry = new MapEntry();
|
|
+ public FastEntryIterator() {}
|
|
+ public FastEntryIterator( long from ) {
|
|
+ super( from );
|
|
+ }
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public MapEntry previous() {
|
|
+ entry.index = previousEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ public void set( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long2ObjectMap.Entry <V> ok ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSortedSet<Long2ObjectMap.Entry <V> > implements FastSortedEntrySet <V> {
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public Comparator<? super Long2ObjectMap.Entry <V> > comparator() { return null; }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > subSet( Long2ObjectMap.Entry <V> fromElement, Long2ObjectMap.Entry <V> toElement) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > headSet( Long2ObjectMap.Entry <V> toElement ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > tailSet( Long2ObjectMap.Entry <V> fromElement ) { throw new UnsupportedOperationException(); }
|
|
+ public Long2ObjectMap.Entry <V> first() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Long2ObjectLinkedOpenHashMap.this.first );
|
|
+ }
|
|
+ public Long2ObjectMap.Entry <V> last() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return new MapEntry( Long2ObjectLinkedOpenHashMap.this.last );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Long2ObjectLinkedOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectLinkedOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > iterator( final Long2ObjectMap.Entry <V> from ) {
|
|
+ return new EntryIterator( from.getLongKey() );
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( final Long2ObjectMap.Entry <V> from ) {
|
|
+ return new FastEntryIterator( from.getLongKey() );
|
|
+ }
|
|
+ }
|
|
+ public FastSortedEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongListIterator {
|
|
+ public KeyIterator( final long k ) { super( k ); }
|
|
+ public long previousLong() { return key[ previousEntry() ]; }
|
|
+ public void set( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long previous() { return (Long.valueOf(key[ previousEntry() ])); }
|
|
+ public void set( Long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( Long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSortedSet {
|
|
+ public LongListIterator iterator( final long from ) {
|
|
+ return new KeyIterator( from );
|
|
+ }
|
|
+ public LongListIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectLinkedOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ public long firstLong() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ first ];
|
|
+ }
|
|
+ public long lastLong() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ return key[ last ];
|
|
+ }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ final public LongSortedSet tailSet( long from ) { throw new UnsupportedOperationException(); }
|
|
+ final public LongSortedSet headSet( long to ) { throw new UnsupportedOperationException(); }
|
|
+ final public LongSortedSet subSet( long from, long to ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ public LongSortedSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectListIterator <V> {
|
|
+ public V previous() { return value[ previousEntry() ]; }
|
|
+ public void set( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( V v ) { throw new UnsupportedOperationException(); }
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectLinkedOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = first, prev = -1, newPrev = -1, t, pos;
|
|
+ final long link[] = this.link;
|
|
+ final long newLink[] = new long[ newN + 1 ];
|
|
+ first = -1;
|
|
+ for( int j = size; j-- != 0; ) {
|
|
+ if ( ( (key[ i ]) == (0) ) ) pos = newN;
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask;
|
|
+ while ( ! ( (newKey[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ if ( prev != -1 ) {
|
|
+ newLink[ newPrev ] ^= ( ( newLink[ newPrev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ newLink[ pos ] ^= ( ( newLink[ pos ] ^ ( ( newPrev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ newPrev = pos;
|
|
+ }
|
|
+ else {
|
|
+ newPrev = first = pos;
|
|
+ // Special case of SET(newLink[ pos ], -1, -1);
|
|
+ newLink[ pos ] = -1L;
|
|
+ }
|
|
+ t = i;
|
|
+ i = (int) link[ i ];
|
|
+ prev = t;
|
|
+ }
|
|
+ this.link = newLink;
|
|
+ this.last = newPrev;
|
|
+ if ( newPrev != -1 )
|
|
+ // Special case of SET_NEXT( newLink[ newPrev ], -1 );
|
|
+ newLink[ newPrev ] |= -1 & 0xFFFFFFFFL;
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectLinkedOpenHashMap <V> clone() {
|
|
+ Long2ObjectLinkedOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectLinkedOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.link = link.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ final long link[] = this.link = new long[ n + 1 ];
|
|
+ int prev = -1;
|
|
+ first = last = -1;
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( first != -1 ) {
|
|
+ link[ prev ] ^= ( ( link[ prev ] ^ ( pos & 0xFFFFFFFFL ) ) & 0xFFFFFFFFL );
|
|
+ link[ pos ] ^= ( ( link[ pos ] ^ ( ( prev & 0xFFFFFFFFL ) << 32 ) ) & 0xFFFFFFFF00000000L );
|
|
+ prev = pos;
|
|
+ }
|
|
+ else {
|
|
+ prev = first = pos;
|
|
+ // Special case of SET_PREV( newLink[ pos ], -1 );
|
|
+ link[ pos ] |= (-1L & 0xFFFFFFFFL) << 32;
|
|
+ }
|
|
+ }
|
|
+ last = prev;
|
|
+ if ( prev != -1 )
|
|
+ // Special case of SET_NEXT( link[ prev ], -1 );
|
|
+ link[ prev ] |= -1 & 0xFFFFFFFFL;
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import java.util.Map;
|
|
+/** A type-specific {@link Map}; provides some additional methods that use polymorphism to avoid (un)boxing, and handling of a default return value.
|
|
+ *
|
|
+ * <P>Besides extending the corresponding type-specific {@linkplain it.unimi.dsi.fastutil.Function function}, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()} and {@link #values()}. Maps returning entry sets of type {@link FastEntrySet} support also fast iteration.
|
|
+ *
|
|
+ * <P>A submap or subset may or may not have an
|
|
+ * independent default return value (which however must be initialized to the
|
|
+ * default return value of the originator).
|
|
+ *
|
|
+ * @see Map
|
|
+ */
|
|
+public interface Long2ObjectMap <V> extends Long2ObjectFunction <V>, Map<Long,V> {
|
|
+ /** An entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of {@link java.util.Map.Entry} objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastEntrySet <V> extends ObjectSet<Long2ObjectMap.Entry <V> > {
|
|
+ /** Returns a fast iterator over this entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this entry set; the iterator might return always the same {@link java.util.Map.Entry} object, suitably mutated.
|
|
+ */
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator();
|
|
+ }
|
|
+ /** Returns a set view of the mappings contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#entrySet()}.
|
|
+ *
|
|
+ * @return a set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSet<Map.Entry<Long, V>> entrySet();
|
|
+ /** Returns a type-specific set view of the mappings contained in this map.
|
|
+ *
|
|
+ * <p>This method is necessary because there is no inheritance along
|
|
+ * type parameters: it is thus impossible to strengthen {@link #entrySet()}
|
|
+ * so that it returns an {@link it.unimi.dsi.fastutil.objects.ObjectSet}
|
|
+ * of type-specific entries (the latter makes it possible to
|
|
+ * access keys and values with type-specific methods).
|
|
+ *
|
|
+ * @return a type-specific set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
|
|
+ /** Returns a set view of the keys contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#keySet()}.
|
|
+ *
|
|
+ * @return a set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ LongSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** A type-specific {@link java.util.Map.Entry}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * @see java.util.Map.Entry
|
|
+ */
|
|
+ interface Entry <V> extends Map.Entry <Long,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ Long getKey();
|
|
+ /**
|
|
+ * @see java.util.Map.Entry#getKey()
|
|
+ */
|
|
+ long getLongKey();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectMaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollections;
|
|
+import java.util.Map;
|
|
+/** A class providing static methods and objects that do useful things with type-specific maps.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Maps
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectMaps {
|
|
+ private Long2ObjectMaps() {}
|
|
+ /** An immutable class representing an empty type-specific map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class EmptyMap <V> extends Long2ObjectFunctions.EmptyFunction <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyMap() {}
|
|
+ public boolean containsValue( final Object v ) { return false; }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSets.EMPTY_SET; }
|
|
+
|
|
+ public LongSet keySet() { return LongSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectCollection <V> values() { return ObjectSets.EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_MAP; }
|
|
+ public Object clone() { return EMPTY_MAP; }
|
|
+ public boolean isEmpty() { return true; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ return ((Map<?,?>)o).isEmpty();
|
|
+ }
|
|
+ public String toString() { return "{}"; }
|
|
+ }
|
|
+ /** An empty type-specific map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptyMap EMPTY_MAP = new EmptyMap();
|
|
+ /** Return an empty map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Long2ObjectMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Long2ObjectFunctions.Singleton <V> implements Long2ObjectMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected transient ObjectSet<Long2ObjectMap.Entry <V> > entries;
|
|
+ protected transient LongSet keys;
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ super( key, value );
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) { return ( (value) == null ? (v) == null : (value).equals(v) ); }
|
|
+ public void putAll( final Map<? extends Long, ? extends V> m ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry() ); return entries; }
|
|
+ public LongSet keySet() { if ( keys == null ) keys = LongSets.singleton( key ); return keys; }
|
|
+ public ObjectCollection <V> values() { if ( values == null ) values = ObjectSets.singleton( value ); return values; }
|
|
+ protected class SingletonEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long,V> {
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() { return (Long.valueOf(Singleton.this.key)); }
|
|
+ public V getValue() { return (Singleton.this.value); }
|
|
+ public long getLongKey() { return Singleton.this.key; }
|
|
+ public V setValue( final V value ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<?,?> e = (Map.Entry<?,?>)o;
|
|
+ return ( (Singleton.this.key) == (((((Long)(e.getKey())).longValue()))) ) && ( (Singleton.this.value) == null ? ((e.getValue())) == null : (Singleton.this.value).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(Singleton.this.key) ^ ( (Singleton.this.value) == null ? 0 : (Singleton.this.value).hashCode() ); }
|
|
+ public String toString() { return Singleton.this.key + "->" + Singleton.this.value; }
|
|
+ }
|
|
+ public boolean isEmpty() { return false; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSet<Map.Entry<Long, V>> entrySet() { return (ObjectSet)long2ObjectEntrySet(); }
|
|
+ public int hashCode() { return it.unimi.dsi.fastutil.HashCommon.long2int(key) ^ ( (value) == null ? 0 : (value).hashCode() ); }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Map ) ) return false;
|
|
+ Map<?,?> m = (Map<?,?>)o;
|
|
+ if ( m.size() != 1 ) return false;
|
|
+ return entrySet().iterator().next().equals( m.entrySet().iterator().next() );
|
|
+ }
|
|
+ public String toString() { return "{" + key + "=>" + value + "}"; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable map containing only the specified pair. The returned map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned map.
|
|
+ * @param value the only value of the returned map.
|
|
+ * @return a type-specific immutable map containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenCustomHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectOpenCustomHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The hash strategy of this custom map. */
|
|
+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenCustomHashMap( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Map<? extends Long, ? extends V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m.size(), f, strategy );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final Long2ObjectMap <V> m, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( k.length, f, strategy );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param strategy the strategy.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenCustomHashMap( final long[] k, final V[] v, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash map.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( strategy.equals( (key[ index ]), (((e.getKey()).longValue())) ) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return ( strategy.hashCode(key[ index ]) ) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Long2ObjectOpenCustomHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final long key[] = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final long k = wrapped.getLong( - pos - 1 );
|
|
+ int p = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( strategy.equals( (k), (key[ p ]) ) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Long2ObjectOpenCustomHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Long2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) return ( Long2ObjectOpenCustomHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenCustomHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSet {
|
|
+ public LongIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectOpenCustomHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public LongSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenCustomHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenCustomHashMap <V> clone() {
|
|
+ Long2ObjectOpenCustomHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectOpenCustomHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = ( strategy.hashCode(key[ i ]) );
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectOpenHashMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Map;
|
|
+import java.util.Arrays;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
+import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
|
+/** A type-specific hash map with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a map. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class Long2ObjectOpenHashMap <V> extends AbstractLong2ObjectMap <V> implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The array of values. */
|
|
+ protected transient V[] value;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the key zero. */
|
|
+ protected transient boolean containsNullKey;
|
|
+ /** The current table size. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the key zero, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Cached set of entries. */
|
|
+ protected transient FastEntrySet <V> entries;
|
|
+ /** Cached set of keys. */
|
|
+ protected transient LongSet keys;
|
|
+ /** Cached collection of values. */
|
|
+ protected transient ObjectCollection <V> values;
|
|
+ /** Creates a new hash map.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenHashMap( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ value = (V[]) new Object[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} entries
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given one.
|
|
+ *
|
|
+ * @param m a {@link Map} to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Map<? extends Long, ? extends V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m, final float f ) {
|
|
+ this( m.size(), f );
|
|
+ putAll( m );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor copying a given type-specific one.
|
|
+ *
|
|
+ * @param m a type-specific map to be copied into the new hash map.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final Long2ObjectMap <V> m ) {
|
|
+ this( m, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash map using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @param f the load factor.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final long[] k, final V[] v, final float f ) {
|
|
+ this( k.length, f );
|
|
+ if ( k.length != v.length ) throw new IllegalArgumentException( "The key array and the value array have different lengths (" + k.length + " and " + v.length + ")" );
|
|
+ for( int i = 0; i < k.length; i++ ) this.put( k[ i ], v[ i ] );
|
|
+ }
|
|
+ /** Creates a new hash map with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using the elements of two parallel arrays.
|
|
+ *
|
|
+ * @param k the array of keys of the new hash map.
|
|
+ * @param v the array of corresponding values in the new hash map.
|
|
+ * @throws IllegalArgumentException if <code>k</code> and <code>v</code> have different lengths.
|
|
+ */
|
|
+ public Long2ObjectOpenHashMap( final long[] k, final V[] v ) {
|
|
+ this( k, v, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNullKey ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private V removeEntry( final int pos ) {
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = null;
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ private V removeNullEntry() {
|
|
+ containsNullKey = false;
|
|
+ final V oldValue = value[ n ];
|
|
+ value[ n ] = null;
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public void putAll(Map<? extends Long,? extends V> m) {
|
|
+ if ( f <= .5 ) ensureCapacity( m.size() ); // The resulting map will be sized for m.size() elements
|
|
+ else tryCapacity( size() + m.size() ); // The resulting map will be tentatively sized for size() + m.size() elements
|
|
+ super.putAll( m );
|
|
+ }
|
|
+ private int insert(final long k, final V v) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return n;
|
|
+ containsNullKey = true;
|
|
+ pos = n;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return pos;
|
|
+ }
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return -1;
|
|
+ }
|
|
+ public V put(final long k, final V v) {
|
|
+ final int pos = insert( k, v );
|
|
+ if ( pos < 0 ) return defRetValue;
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public V put( final Long ok, final V ov ) {
|
|
+ final V v = (ov);
|
|
+ final int pos = insert( ((ok).longValue()), v );
|
|
+ if ( pos < 0 ) return (this.defRetValue);
|
|
+ final V oldValue = value[ pos ];
|
|
+ value[ pos ] = v;
|
|
+ return (oldValue);
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return removeNullEntry();
|
|
+ return defRetValue;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+
|
|
+ public V remove( final Object ok ) {
|
|
+ final long k = ((((Long)(ok)).longValue()));
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey ) return (removeNullEntry());
|
|
+ return (this.defRetValue);
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (curr) == (k) ) ) return (removeEntry( pos ));
|
|
+ }
|
|
+ }
|
|
+ /** @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public V get( final Long ok ) {
|
|
+ if ( ok == null ) return null;
|
|
+ final long k = ((ok).longValue());
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? (value[ n ]) : (this.defRetValue);
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return (this.defRetValue);
|
|
+ if ( ( (k) == (curr) ) ) return (value[ pos ]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public V get( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey ? value[ n ] : defRetValue;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return defRetValue;
|
|
+ if ( ( (k) == (curr) ) ) return value[ pos ];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean containsKey( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNullKey;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ public boolean containsValue( final Object v ) {
|
|
+ final V value[] = this.value;
|
|
+ final long key[] = this.key;
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) return true;
|
|
+ for( int i = n; i-- != 0; ) if ( ! ( (key[ i ]) == (0) ) && ( (value[ i ]) == null ? (v) == null : (value[ i ]).equals(v) ) ) return true;
|
|
+ return false;
|
|
+ }
|
|
+ /* Removes all elements from this map.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNullKey = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ Arrays.fill( value, null );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** The entry class for a hash map does not record key and value, but
|
|
+ * rather the position in the hash table of the corresponding entry. This
|
|
+ * is necessary so that calls to {@link java.util.Map.Entry#setValue(Object)} are reflected in
|
|
+ * the map */
|
|
+ final class MapEntry implements Long2ObjectMap.Entry <V>, Map.Entry<Long, V> {
|
|
+ // The table index this entry refers to, or -1 if this entry has been deleted.
|
|
+ int index;
|
|
+ MapEntry( final int index ) {
|
|
+ this.index = index;
|
|
+ }
|
|
+ MapEntry() {}
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long getKey() {
|
|
+ return (Long.valueOf(key[ index ]));
|
|
+ }
|
|
+ public long getLongKey() {
|
|
+ return key[ index ];
|
|
+ }
|
|
+ public V getValue() {
|
|
+ return (value[ index ]);
|
|
+ }
|
|
+ public V setValue( final V v ) {
|
|
+ final V oldValue = value[ index ];
|
|
+ value[ index ] = v;
|
|
+ return oldValue;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean equals( final Object o ) {
|
|
+ if (!(o instanceof Map.Entry)) return false;
|
|
+ Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ return ( (key[ index ]) == (((e.getKey()).longValue())) ) && ( (value[ index ]) == null ? ((e.getValue())) == null : (value[ index ]).equals((e.getValue())) );
|
|
+ }
|
|
+ public int hashCode() {
|
|
+ return it.unimi.dsi.fastutil.HashCommon.long2int(key[ index ]) ^ ( (value[ index ]) == null ? 0 : (value[ index ]).hashCode() );
|
|
+ }
|
|
+ public String toString() {
|
|
+ return key[ index ] + "=>" + value[ index ];
|
|
+ }
|
|
+ }
|
|
+ /** An iterator over a hash map. */
|
|
+ private class MapIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ entry returned was that of the key of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the entry with the null key. */
|
|
+ boolean mustReturnNullKey = Long2ObjectOpenHashMap.this.containsNullKey;
|
|
+ /** A lazily allocated list containing keys of entries that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public int nextEntry() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNullKey ) {
|
|
+ mustReturnNullKey = false;
|
|
+ return last = n;
|
|
+ }
|
|
+ final long key[] = Long2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ final long k = wrapped.getLong( - pos - 1 );
|
|
+ int p = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (k) == (key[ p ]) ) ) p = ( p + 1 ) & mask;
|
|
+ return p;
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return last = pos;
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ value[ last ] = null;
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ value[ last ] = value[ pos ];
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ containsNullKey = false;
|
|
+ value[ n ] = null;
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ Long2ObjectOpenHashMap.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) nextEntry();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+ }
|
|
+ private class EntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private MapEntry entry;
|
|
+ public Long2ObjectMap.Entry <V> next() {
|
|
+ return entry = new MapEntry( nextEntry() );
|
|
+ }
|
|
+ @Override
|
|
+ public void remove() {
|
|
+ super.remove();
|
|
+ entry.index = -1; // You cannot use a deleted entry.
|
|
+ }
|
|
+ }
|
|
+ private class FastEntryIterator extends MapIterator implements ObjectIterator<Long2ObjectMap.Entry <V> > {
|
|
+ private final MapEntry entry = new MapEntry();
|
|
+ public MapEntry next() {
|
|
+ entry.index = nextEntry();
|
|
+ return entry;
|
|
+ }
|
|
+ }
|
|
+ private final class MapEntrySet extends AbstractObjectSet<Long2ObjectMap.Entry <V> > implements FastEntrySet <V> {
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > iterator() {
|
|
+ return new EntryIterator();
|
|
+ }
|
|
+ public ObjectIterator<Long2ObjectMap.Entry <V> > fastIterator() {
|
|
+ return new FastEntryIterator();
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean contains( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ if ( ( (k) == (0) ) ) return ( Long2ObjectOpenHashMap.this.containsNullKey && ( (value[ n ]) == null ? ((e.getValue())) == null : (value[ n ]).equals((e.getValue())) ) );
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ // There's always an unused entry.
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return ( (value[ pos ]) == null ? ((e.getValue())) == null : (value[ pos ]).equals((e.getValue())) );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public boolean remove( final Object o ) {
|
|
+ if ( !( o instanceof Map.Entry ) ) return false;
|
|
+ final Map.Entry<Long, V> e = (Map.Entry<Long, V>)o;
|
|
+ if ( e.getKey() == null ) return false;
|
|
+ final long k = ((e.getKey()).longValue());
|
|
+ final V v = (e.getValue());
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNullKey && ( (value[ n ]) == null ? (v) == null : (value[ n ]).equals(v) ) ) {
|
|
+ removeNullEntry();
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = Long2ObjectOpenHashMap.this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (curr) == (k) ) ) {
|
|
+ if ( ( (value[ pos ]) == null ? (v) == null : (value[ pos ]).equals(v) ) ) {
|
|
+ removeEntry( pos );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public FastEntrySet <V> long2ObjectEntrySet() {
|
|
+ if ( entries == null ) entries = new MapEntrySet();
|
|
+ return entries;
|
|
+ }
|
|
+ /** An iterator on keys.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return keys
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class KeyIterator extends MapIterator implements LongIterator {
|
|
+ public KeyIterator() { super(); }
|
|
+ public long nextLong() { return key[ nextEntry() ]; }
|
|
+ public Long next() { return (Long.valueOf(key[ nextEntry() ])); }
|
|
+ }
|
|
+ private final class KeySet extends AbstractLongSet {
|
|
+ public LongIterator iterator() {
|
|
+ return new KeyIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( long k ) {
|
|
+ return containsKey( k );
|
|
+ }
|
|
+ public boolean remove( long k ) {
|
|
+ final int oldSize = size;
|
|
+ Long2ObjectOpenHashMap.this.remove( k );
|
|
+ return size != oldSize;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ }
|
|
+ public LongSet keySet() {
|
|
+ if ( keys == null ) keys = new KeySet();
|
|
+ return keys;
|
|
+ }
|
|
+ /** An iterator on values.
|
|
+ *
|
|
+ * <P>We simply override the {@link java.util.ListIterator#next()}/{@link java.util.ListIterator#previous()} methods
|
|
+ * (and possibly their type-specific counterparts) so that they return values
|
|
+ * instead of entries.
|
|
+ */
|
|
+ private final class ValueIterator extends MapIterator implements ObjectIterator <V> {
|
|
+ public ValueIterator() { super(); }
|
|
+ public V next() { return value[ nextEntry() ]; }
|
|
+ }
|
|
+ public ObjectCollection <V> values() {
|
|
+ if ( values == null ) values = new AbstractObjectCollection <V>() {
|
|
+ public ObjectIterator <V> iterator() {
|
|
+ return new ValueIterator();
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean contains( Object v ) {
|
|
+ return containsValue( v );
|
|
+ }
|
|
+ public void clear() {
|
|
+ Long2ObjectOpenHashMap.this.clear();
|
|
+ }
|
|
+ };
|
|
+ return values;
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this map if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this map in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing maps. {@linkplain #clear() Clearing a
|
|
+ * map} leaves the table size untouched. If you are reusing a map
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient maps.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the map.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the map.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ final V newValue[] = (V[]) new Object[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ newValue[ pos ] = value[ i ];
|
|
+ }
|
|
+ newValue[ newN ] = value[ n ];
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ this.value = newValue;
|
|
+ }
|
|
+ /** Returns a deep copy of this map.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash map; the data stored in the
|
|
+ * map, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this map.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectOpenHashMap <V> clone() {
|
|
+ Long2ObjectOpenHashMap <V> c;
|
|
+ try {
|
|
+ c = (Long2ObjectOpenHashMap <V>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.keys = null;
|
|
+ c.values = null;
|
|
+ c.entries = null;
|
|
+ c.containsNullKey = containsNullKey;
|
|
+ c.key = key.clone();
|
|
+ c.value = value.clone();
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this map.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this map.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0, t = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ t = it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ if ( this != value[ i ] )
|
|
+ t ^= ( (value[ i ]) == null ? 0 : (value[ i ]).hashCode() );
|
|
+ h += t;
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null keys have hash zero.
|
|
+ if ( containsNullKey ) h += ( (value[ n ]) == null ? 0 : (value[ n ]).hashCode() );
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final long key[] = this.key;
|
|
+ final V value[] = this.value;
|
|
+ final MapIterator i = new MapIterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size, e; j-- != 0; ) {
|
|
+ e = i.nextEntry();
|
|
+ s.writeLong( key[ e ] );
|
|
+ s.writeObject( value[ e ] );
|
|
+ }
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ final V value[] = this.value = (V[]) new Object[ n + 1 ];
|
|
+ long k;
|
|
+ V v;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ v = (V) s.readObject();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNullKey = true;
|
|
+ }
|
|
+ else {
|
|
+ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask;
|
|
+ while ( ! ( (key[ pos ]) == (0) ) ) pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ value[ pos ] = v;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMap.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+/** A type-specific {@link SortedMap}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #entrySet()},
|
|
+ * {@link #keySet()}, {@link #values()},
|
|
+ * {@link #comparator()}, {@link SortedMap#subMap(Object,Object)}, {@link SortedMap#headMap(Object)} and {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap
|
|
+ */
|
|
+public interface Long2ObjectSortedMap <V> extends Long2ObjectMap <V>, SortedMap<Long, V> {
|
|
+ /** A sorted entry set providing fast iteration.
|
|
+ *
|
|
+ * <p>In some cases (e.g., hash-based classes) iteration over an entry set requires the creation
|
|
+ * of a large number of entry objects. Some <code>fastutil</code>
|
|
+ * maps might return {@linkplain #entrySet() entry set} objects of type <code>FastSortedEntrySet</code>: in this case, {@link #fastIterator() fastIterator()}
|
|
+ * will return an iterator that is guaranteed not to create a large number of objects, <em>possibly
|
|
+ * by returning always the same entry</em> (of course, mutated).
|
|
+ */
|
|
+ public interface FastSortedEntrySet <V> extends ObjectSortedSet<Long2ObjectMap.Entry <V> >, FastEntrySet <V> {
|
|
+ /** Returns a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ *
|
|
+ * @return a fast iterator over this sorted entry set; the iterator might return always the same entry object, suitably mutated.
|
|
+ */
|
|
+ public ObjectBidirectionalIterator<Long2ObjectMap.Entry <V> > fastIterator( Long2ObjectMap.Entry <V> from );
|
|
+ }
|
|
+ /** Returns a sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the mappings contained in this map.
|
|
+ * @see Map#entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Map.Entry<Long, V>> entrySet();
|
|
+ /** Returns a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a type-specific sorted-set view of the mappings contained in this map.
|
|
+ * @see #entrySet()
|
|
+ */
|
|
+ ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet();
|
|
+ /** Returns a sorted-set view of the keys contained in this map.
|
|
+ * Note that this specification strengthens the one given in the
|
|
+ * corresponding type-specific unsorted map.
|
|
+ *
|
|
+ * @return a sorted-set view of the keys contained in this map.
|
|
+ * @see Map#keySet()
|
|
+ */
|
|
+ LongSortedSet keySet();
|
|
+ /** Returns a set view of the values contained in this map.
|
|
+ * <P>Note that this specification strengthens the one given in {@link Map#values()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link SortedMap}.
|
|
+ *
|
|
+ * @return a set view of the values contained in this map.
|
|
+ * @see Map#values()
|
|
+ */
|
|
+ ObjectCollection <V> values();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its keys' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#comparator()}.
|
|
+ *
|
|
+ * @see SortedMap#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#subMap(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> subMap(Long fromKey, Long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#headMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> headMap(Long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedMap#tailMap(Object)}.
|
|
+ *
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> tailMap(Long fromKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys range from <code>fromKey</code>, inclusive, to <code>toKey</code>, exclusive.
|
|
+ * @see SortedMap#subMap(Object,Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> subMap(long fromKey, long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are strictly less than <code>toKey</code>.
|
|
+ * @see SortedMap#headMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> headMap(long toKey);
|
|
+ /** Returns a view of the portion of this sorted map whose keys are greater than or equal to <code>fromKey</code>.
|
|
+ * @see SortedMap#tailMap(Object)
|
|
+ */
|
|
+ Long2ObjectSortedMap <V> tailMap(long fromKey);
|
|
+ /**
|
|
+ * @see SortedMap#firstKey()
|
|
+ */
|
|
+ long firstLongKey();
|
|
+ /**
|
|
+ * @see SortedMap#lastKey()
|
|
+ */
|
|
+ long lastLongKey();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/Long2ObjectSortedMaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectSortedSets;
|
|
+import java.util.Comparator;
|
|
+import java.util.Map;
|
|
+import java.util.SortedMap;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted maps.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class Long2ObjectSortedMaps {
|
|
+ private Long2ObjectSortedMaps() {}
|
|
+ /** Returns a comparator for entries based on a given comparator on keys.
|
|
+ *
|
|
+ * @param comparator a comparator on keys.
|
|
+ * @return the associated comparator on entries.
|
|
+ */
|
|
+ public static Comparator<? super Map.Entry<Long, ?>> entryComparator( final LongComparator comparator ) {
|
|
+ return new Comparator<Map.Entry<Long, ?>>() {
|
|
+ public int compare( Map.Entry<Long, ?> x, Map.Entry<Long, ?> y ) {
|
|
+ return comparator.compare( x.getKey(), y.getKey() );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class EmptySortedMap <V> extends Long2ObjectMaps.EmptyMap <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySortedMap() {}
|
|
+ public LongComparator comparator() { return null; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return ObjectSortedSets.EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet keySet() { return LongSortedSets.EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { return EMPTY_MAP; }
|
|
+ public long firstLongKey() { throw new NoSuchElementException(); }
|
|
+ public long lastLongKey() { throw new NoSuchElementException(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() { return (Long.valueOf(firstLongKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() { return (Long.valueOf(lastLongKey())); }
|
|
+ }
|
|
+ /** An empty sorted map (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySortedMap EMPTY_MAP = new EmptySortedMap();
|
|
+ /** Return an empty sorted map (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_MAP}.
|
|
+ * @return an empty sorted map (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <V> Long2ObjectSortedMap <V> emptyMap() {
|
|
+ return EMPTY_MAP;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton sorted map.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted map.
|
|
+ */
|
|
+ public static class Singleton <V> extends Long2ObjectMaps.Singleton <V> implements Long2ObjectSortedMap <V>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongComparator comparator;
|
|
+ protected Singleton( final long key, final V value, LongComparator comparator ) {
|
|
+ super( key, value );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ protected Singleton( final long key, final V value ) {
|
|
+ this( key, value, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final long k1, final long k2 ) {
|
|
+ return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ public LongComparator comparator() { return comparator; }
|
|
+
|
|
+ public ObjectSortedSet<Long2ObjectMap.Entry <V> > long2ObjectEntrySet() { if ( entries == null ) entries = ObjectSortedSets.singleton( (Long2ObjectMap.Entry <V>)new SingletonEntry(), (Comparator<? super Long2ObjectMap.Entry <V> >)entryComparator( comparator ) ); return (ObjectSortedSet<Long2ObjectMap.Entry <V> >)entries; }
|
|
+ @SuppressWarnings({ "rawtypes", "unchecked" })
|
|
+ public ObjectSortedSet<Map.Entry<Long, V>> entrySet() { return (ObjectSortedSet)long2ObjectEntrySet(); }
|
|
+ public LongSortedSet keySet() { if ( keys == null ) keys = LongSortedSets.singleton( key, comparator ); return (LongSortedSet )keys; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> subMap( final long from, final long to ) { if ( compare( from, key ) <= 0 && compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> headMap( final long to ) { if ( compare( key, to ) < 0 ) return this; return EMPTY_MAP; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Long2ObjectSortedMap <V> tailMap( final long from ) { if ( compare( from, key ) <= 0 ) return this; return EMPTY_MAP; }
|
|
+ public long firstLongKey() { return key; }
|
|
+ public long lastLongKey() { return key; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> headMap( Long oto ) { return headMap( ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> tailMap( Long ofrom ) { return tailMap( ((ofrom).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long2ObjectSortedMap <V> subMap( Long ofrom, Long oto ) { return subMap( ((ofrom).longValue()), ((oto).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long firstKey() { return (Long.valueOf(firstLongKey())); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long lastKey() { return (Long.valueOf(lastLongKey())); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted map containing only the specified pair. The returned sorted map is serializable and cloneable.
|
|
+ *
|
|
+ * <P>Note that albeit the returned map is immutable, its default return value may be changed.
|
|
+ *
|
|
+ * @param key the only key of the returned sorted map.
|
|
+ * @param value the only value of the returned sorted map.
|
|
+ * @return a type-specific immutable sorted map containing just the pair <code><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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayFIFOQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2010-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.io.Serializable;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based FIFO queue, supporting also deque operations.
|
|
+ *
|
|
+ * <P>Instances of this class represent a FIFO queue using a backing
|
|
+ * array in a circular way. The array is enlarged and shrunk as needed. You can use the {@link #trim()} method
|
|
+ * to reduce its memory usage, if necessary.
|
|
+ *
|
|
+ * <P>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
|
|
+ */
|
|
+public class LongArrayFIFOQueue extends AbstractLongPriorityQueue implements Serializable {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ /** The standard initial capacity of a queue. */
|
|
+ public final static int INITIAL_CAPACITY = 4;
|
|
+ /** The backing array. */
|
|
+ protected transient long array[];
|
|
+ /** The current (cached) length of {@link #array}. */
|
|
+ protected transient int length;
|
|
+ /** The start position in {@link #array}. It is always strictly smaller than {@link #length}.*/
|
|
+ protected transient int start;
|
|
+ /** The end position in {@link #array}. It is always strictly smaller than {@link #length}.
|
|
+ * Might be actually smaller than {@link #start} because {@link #array} is used cyclically. */
|
|
+ protected transient int end;
|
|
+ /** Creates a new empty queue with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+
|
|
+ public LongArrayFIFOQueue( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ array = new long[ Math.max( 1, capacity ) ]; // Never build a queue with zero-sized backing array.
|
|
+ length = array.length;
|
|
+ }
|
|
+ /** Creates a new empty queue with standard {@linkplain #INITIAL_CAPACITY initial capacity}.
|
|
+ */
|
|
+ public LongArrayFIFOQueue() {
|
|
+ this( INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Returns <code>null</code> (FIFO queues have no comparator).
|
|
+ * @return <code>null</code>.
|
|
+ */
|
|
+ @Override
|
|
+ public LongComparator comparator() {
|
|
+ return null;
|
|
+ }
|
|
+ @Override
|
|
+ public long dequeueLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ final long t = array[ start ];
|
|
+ if ( ++start == length ) start = 0;
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+ /** Dequeues the last element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ public long dequeueLastLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ if ( end == 0 ) end = length;
|
|
+ final long t = array[ --end ];
|
|
+ reduce();
|
|
+ return t;
|
|
+ }
|
|
+
|
|
+ private final void resize( final int size, final int newLength ) {
|
|
+ final long[] newArray = new long[ newLength ];
|
|
+ if ( start >= end ) {
|
|
+ if ( size != 0 ) {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ }
|
|
+ else System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ start = 0;
|
|
+ end = size;
|
|
+ array = newArray;
|
|
+ length = newLength;
|
|
+ }
|
|
+ private final void expand() {
|
|
+ resize( length, (int)Math.min( it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE, 2L * length ) );
|
|
+ }
|
|
+ private final void reduce() {
|
|
+ final int size = size();
|
|
+ if ( length > INITIAL_CAPACITY && size <= length / 4 ) resize( size, length / 2 );
|
|
+ }
|
|
+ @Override
|
|
+ public void enqueue( long x ) {
|
|
+ array[ end++ ] = x;
|
|
+ if ( end == length ) end = 0;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Enqueues a new element as the first element (in dequeuing order) of the queue.
|
|
+ */
|
|
+ public void enqueueFirst( long x ) {
|
|
+ if ( start == 0 ) start = length;
|
|
+ array[ --start ] = x;
|
|
+ if ( end == start ) expand();
|
|
+ }
|
|
+ /** Returns the first element of the queue.
|
|
+ * @return the first element of the queue.
|
|
+ */
|
|
+ public long firstLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ start ];
|
|
+ }
|
|
+ /** Returns the last element of the queue.
|
|
+ * @return the last element of the queue.
|
|
+ */
|
|
+ public long lastLong() {
|
|
+ if ( start == end ) throw new NoSuchElementException();
|
|
+ return array[ ( end == 0 ? length : end ) - 1 ];
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ start = end = 0;
|
|
+ }
|
|
+ /** Trims the queue to the smallest possible size. */
|
|
+
|
|
+ public void trim() {
|
|
+ final int size = size();
|
|
+ final long[] newArray =
|
|
+ new long[ size + 1 ];
|
|
+ if ( start <= end ) System.arraycopy( array, start, newArray, 0, end - start );
|
|
+ else {
|
|
+ System.arraycopy( array, start, newArray, 0, length - start );
|
|
+ System.arraycopy( array, 0, newArray, length - start, end );
|
|
+ }
|
|
+ start = 0;
|
|
+ length = ( end = size ) + 1;
|
|
+ array = newArray;
|
|
+ }
|
|
+ @Override
|
|
+ public int size() {
|
|
+ final int apparentLength = end - start;
|
|
+ return apparentLength >= 0 ? apparentLength : length + apparentLength;
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ int size = size();
|
|
+ s.writeInt( size );
|
|
+ for( int i = start; size-- != 0; ) {
|
|
+ s.writeLong( array[ i++ ] );
|
|
+ if ( i == length ) i = 0;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ end = s.readInt();
|
|
+ array = new long[ length = HashCommon.nextPowerOfTwo( end + 1 ) ];
|
|
+ for( int i = 0; i < end; i++ ) array[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling its current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible. The backing array is exposed by the
|
|
+ * {@link #elements()} method.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class LongArrayList extends AbstractLongList implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353130L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** The backing array. */
|
|
+ protected transient long a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected LongArrayList( final long a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+
|
|
+ public LongArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = new long[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public LongArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final Collection<? extends Long> c ) {
|
|
+ this( c.size() );
|
|
+ size = LongIterators.unwrap( LongIterators.asLongIterator( c.iterator() ), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongCollection c ) {
|
|
+ this( c.size() );
|
|
+ size = LongIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongList l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final long a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public LongArrayList( final long a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final Iterator<? extends Long> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public LongArrayList( final LongIterator i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.nextLong() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public long[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static LongArrayList wrap( final long a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final LongArrayList l = new LongArrayList ( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static LongArrayList wrap( final long a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ a = LongArrays.ensureCapacity( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+
|
|
+ private void grow( final int capacity ) {
|
|
+ a = LongArrays.grow( a, capacity, size );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final long k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public long getLong( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final long k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final long k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == (a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public long removeLong( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final long old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final long k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ removeLong( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public long set( final int index, final long k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ long old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (0) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final long t[] = new long[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final long[] a, final int offset, final int length ) {
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final long a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ public long[] toLongArray( long a[] ) {
|
|
+ if ( a == null || a.length < size ) a = new long[ size ];
|
|
+ System.arraycopy( this.a, 0, a, 0, size );
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( int index, final LongCollection c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ final LongIterator i = c.iterator();
|
|
+ size += n;
|
|
+ while( n-- != 0 ) a[ index++ ] = i.nextLong();
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean addAll( final int index, final LongList l ) {
|
|
+ ensureIndex( index );
|
|
+ final int n = l.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ grow( size + n );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + n, size - index );
|
|
+ l.getElements( 0, a, index, n );
|
|
+ size += n;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final LongCollection c ) {
|
|
+ final long[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final long[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( (Long.valueOf(a[ i ])) ) ) a[ j++ ] = a[ i ];
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public LongListIterator listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractLongListIterator () {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public long nextLong() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public long previousLong() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( long k ) {
|
|
+ LongArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( long k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ LongArrayList.this.removeLong( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public LongArrayList clone() {
|
|
+ LongArrayList c = new LongArrayList ( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final LongArrayList l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final long[] a1 = a;
|
|
+ final long[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( a1[ s ] != a2[ s ] ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+
|
|
+ public int compareTo( final LongArrayList l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final long a1[] = a, a2[] = l.a;
|
|
+ long e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( Long.compare((e1),(e2)) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new long[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrayPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based priority queue.
|
|
+ *
|
|
+ * <P>Instances of this class represent a priority queue using a backing
|
|
+ * array—all operations are performed directly on the array. The array is
|
|
+ * enlarged as needed, but it is never shrunk. Use the {@link #trim()} method
|
|
+ * to reduce its size, if necessary.
|
|
+ *
|
|
+ * <P>This implementation is extremely inefficient, but it is difficult to beat
|
|
+ * when the size of the queue is very small.
|
|
+ */
|
|
+public class LongArrayPriorityQueue extends AbstractLongPriorityQueue implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array. */
|
|
+
|
|
+ protected transient long array[] = LongArrays.EMPTY_ARRAY;
|
|
+ /** The number of elements in this queue. */
|
|
+ protected int size;
|
|
+ /** The type-specific comparator used in this queue. */
|
|
+ protected LongComparator c;
|
|
+ /** The first index, cached, if {@link #firstIndexValid} is true. */
|
|
+ transient protected int firstIndex;
|
|
+ /** Whether {@link #firstIndex} contains a valid value. */
|
|
+ transient protected boolean firstIndexValid;
|
|
+ /** Creates a new empty queue with a given capacity and comparator.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+
|
|
+ public LongArrayPriorityQueue( int capacity, LongComparator c ) {
|
|
+ if ( capacity > 0 ) this.array = new long[ capacity ];
|
|
+ this.c = c;
|
|
+ }
|
|
+ /** Creates a new empty queue with a given capacity and using the natural order.
|
|
+ *
|
|
+ * @param capacity the initial capacity of this queue.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( int capacity ) {
|
|
+ this( capacity, null );
|
|
+ }
|
|
+ /** Creates a new empty queue with a given comparator.
|
|
+ *
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( LongComparator c ) {
|
|
+ this( 0, c );
|
|
+ }
|
|
+ /** Creates a new empty queue using the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue() {
|
|
+ this( 0, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, int size, final LongComparator c ) {
|
|
+ this( c );
|
|
+ this.array = a;
|
|
+ this.size = size;
|
|
+ }
|
|
+ /** Wraps a given array in a queue using a given comparator.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param c the comparator used in this queue, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, final LongComparator c ) {
|
|
+ this( a, a.length, c );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ * @param size the number of elements to be included in the queue.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a, int size ) {
|
|
+ this( a, size, null );
|
|
+ }
|
|
+ /** Wraps a given array in a queue using the natural order.
|
|
+ *
|
|
+ * <P>The queue returned by this method will be backed by the given array.
|
|
+ *
|
|
+ * @param a an array.
|
|
+ */
|
|
+ public LongArrayPriorityQueue( final long[] a ) {
|
|
+ this( a, a.length );
|
|
+ }
|
|
+ /** Returns the index of the smallest element. */
|
|
+
|
|
+ private int findFirst() {
|
|
+ if ( firstIndexValid ) return this.firstIndex;
|
|
+ firstIndexValid = true;
|
|
+ int i = size;
|
|
+ int firstIndex = --i;
|
|
+ long first = array[ firstIndex ];
|
|
+ if ( c == null ) { while( i-- != 0 ) if ( ( (array[ i ]) < (first) ) ) first = array[ firstIndex = i ]; }
|
|
+ else while( i-- != 0 ) { if ( c.compare( array[ i ], first ) < 0 ) first = array[ firstIndex = i ]; }
|
|
+ return this.firstIndex = firstIndex;
|
|
+ }
|
|
+ private void ensureNonEmpty() {
|
|
+ if ( size == 0 ) throw new NoSuchElementException();
|
|
+ }
|
|
+
|
|
+ public void enqueue( long x ) {
|
|
+ if ( size == array.length ) array = LongArrays.grow( array, size + 1 );
|
|
+ if ( firstIndexValid ) {
|
|
+ if ( c == null ) { if ( ( (x) < (array[ firstIndex ]) ) ) firstIndex = size; }
|
|
+ else if ( c.compare( x, array[ firstIndex ] ) < 0 ) firstIndex = size;
|
|
+ }
|
|
+ else firstIndexValid = false;
|
|
+ array[ size++ ] = x;
|
|
+ }
|
|
+ public long dequeueLong() {
|
|
+ ensureNonEmpty();
|
|
+ final int first = findFirst();
|
|
+ final long result = array[ first ];
|
|
+ System.arraycopy( array, first + 1, array, first, --size - first );
|
|
+ firstIndexValid = false;
|
|
+ return result;
|
|
+ }
|
|
+ public long firstLong() {
|
|
+ ensureNonEmpty();
|
|
+ return array[ findFirst() ];
|
|
+ }
|
|
+ public void changed() {
|
|
+ ensureNonEmpty();
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ public int size() { return size; }
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ firstIndexValid = false;
|
|
+ }
|
|
+ /** Trims the underlying array so that it has exactly {@link #size()} elements.
|
|
+ */
|
|
+ public void trim() {
|
|
+ array = LongArrays.trim( array, size );
|
|
+ }
|
|
+ public LongComparator comparator() { return c; }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ s.writeInt( array.length );
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( array[ i ] );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ array = new long[ s.readInt() ];
|
|
+ for( int i = 0; i < size; i++ ) array[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArraySet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class LongArraySet extends AbstractLongSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient long[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public LongArraySet( final long[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public LongArraySet() {
|
|
+ this.a = LongArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public LongArraySet( final int capacity ) {
|
|
+ this.a = new long[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public LongArraySet( LongCollection c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public LongArraySet( final Collection<? extends Long> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public LongArraySet( final long[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final long o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == (o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+
|
|
+ public LongIterator iterator() {
|
|
+ return new AbstractLongIterator () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final long k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final long k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final long k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final long[] b = new long[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongArraySet clone() {
|
|
+ LongArraySet c;
|
|
+ try {
|
|
+ c = (LongArraySet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeLong( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new long[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readLong();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongArrays.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.concurrent.Callable;
|
|
+import java.util.concurrent.ExecutorCompletionService;
|
|
+import java.util.concurrent.ExecutorService;
|
|
+import java.util.concurrent.Executors;
|
|
+import java.util.concurrent.LinkedBlockingQueue;
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * <p>In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P>Note that {@link it.unimi.dsi.fastutil.io.BinIO} and {@link it.unimi.dsi.fastutil.io.TextIO}
|
|
+ * contain several methods make it possible to load and save arrays of primitive types as sequences
|
|
+ * of elements in {@link java.io.DataInput} format (i.e., not as objects) or as sequences of lines of text.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ * Some algorithms also provide an explicit <em>indirect</em> sorting facility, which makes it possible
|
|
+ * to sort an array using the values in another array as comparator.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>As a general rule, sequential radix sort is significantly faster than quicksort or mergesort, in particular
|
|
+ * on random-looking data. In
|
|
+ * the parallel case, up to a few cores parallel radix sort is still the fastest, but at some point quicksort
|
|
+ * exploits parallelism better.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class LongArrays {
|
|
+ private LongArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static long[] EMPTY_ARRAY = {};
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static long[] ensureCapacity( final long[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final long t[] =
|
|
+ new long[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static long[] ensureCapacity( final long[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final long t[] =
|
|
+ new long[ length ];
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectBidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface LongBidirectionalIterator extends LongIterator , ObjectBidirectionalIterator<Long> {
|
|
+ /**
|
|
+ * Returns the previous element as a primitive type.
|
|
+ *
|
|
+ * @return the previous element in the iteration.
|
|
+ * @see java.util.ListIterator#previous()
|
|
+ */
|
|
+ long previousLong();
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface LongCollection extends Collection<Long>, LongIterable {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ LongIterator iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongIterator longIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+ /**
|
|
+ * @see Collection#contains(Object)
|
|
+ */
|
|
+ boolean contains( long key );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray()
|
|
+ */
|
|
+ long[] toLongArray();
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ long[] toLongArray( long a[] );
|
|
+ /** Returns a primitive type array containing the items of this collection.
|
|
+ *
|
|
+ * <p>Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ long[] toArray( long a[] );
|
|
+ /**
|
|
+ * @see Collection#add(Object)
|
|
+ */
|
|
+ boolean add( long key );
|
|
+ /** Note that this method should be called {@link java.util.Collection#remove(Object) remove()}, but the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface
|
|
+ * forces us to use a distinguished name. For simplicity, the set interfaces reinstates
|
|
+ * <code>remove()</code>.
|
|
+ *
|
|
+ * @see Collection#remove(Object)
|
|
+ */
|
|
+ boolean rem( long key );
|
|
+ /**
|
|
+ * @see Collection#addAll(Collection)
|
|
+ */
|
|
+ boolean addAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#containsAll(Collection)
|
|
+ */
|
|
+ boolean containsAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#removeAll(Collection)
|
|
+ */
|
|
+ boolean removeAll( LongCollection c );
|
|
+ /**
|
|
+ * @see Collection#retainAll(Collection)
|
|
+ */
|
|
+ boolean retainAll( LongCollection c );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongCollections.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongCollections {
|
|
+ private LongCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection extends AbstractLongCollection {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( long k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public long[] toLongArray( long[] a ) { return a; }
|
|
+ public long[] toLongArray() { return LongArrays.EMPTY_ARRAY; }
|
|
+ public boolean rem( long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( LongCollection c ) { return c.isEmpty(); }
|
|
+
|
|
+ public LongBidirectionalIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection implements LongCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongCollection collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final LongCollection c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final LongCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final long o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public long[] toLongArray() { synchronized( sync ) { return collection.toLongArray(); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public long[] toLongArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
|
|
+ public long[] toArray( final long[] a ) { synchronized( sync ) { return collection.toLongArray( a ); } }
|
|
+ public boolean addAll( final LongCollection c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final LongCollection c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final LongCollection c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final LongCollection c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public boolean add( final Long k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean contains( final Object k ) { synchronized( sync ) { return collection.contains( k ); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public LongIterator iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ public boolean add( final long k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final long k ) { synchronized( sync ) { return collection.rem( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection synchronize( final LongCollection c ) { return new SynchronizedCollection ( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection synchronize( final LongCollection c, final Object sync ) { return new SynchronizedCollection ( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection implements LongCollection , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongCollection collection;
|
|
+ protected UnmodifiableCollection( final LongCollection c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final long o ) { return collection.contains( o ); }
|
|
+ public LongIterator iterator() { return LongIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ public long[] toLongArray() { return collection.toLongArray(); }
|
|
+ public long[] toLongArray( final long[] a ) { return collection.toLongArray( a ); }
|
|
+ public long[] toArray( final long[] a ) { return collection.toArray( a ); }
|
|
+ public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final LongCollection c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return collection.contains( k ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static LongCollection unmodifiable( final LongCollection c ) { return new UnmodifiableCollection ( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection extends AbstractLongCollection implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongIterable iterable;
|
|
+ protected IterableCollection( final LongIterable iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final LongIterator iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public LongIterator iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public LongIterator longIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static LongCollection asCollection( final LongIterable iterable ) {
|
|
+ if ( iterable instanceof LongCollection ) return (LongCollection )iterable;
|
|
+ return new IterableCollection ( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Comparator;
|
|
+/** A type-specific {@link Comparator}; provides methods to compare two primitive types both as objects
|
|
+ * and as primitive types.
|
|
+ *
|
|
+ * <P>Note that <code>fastutil</code> provides a corresponding abstract class that
|
|
+ * can be used to implement this interface just by specifying the type-specific
|
|
+ * comparator.
|
|
+ *
|
|
+ * @see Comparator
|
|
+ */
|
|
+public interface LongComparator extends Comparator<Long> {
|
|
+ /** Compares the given primitive types.
|
|
+ *
|
|
+ * @see java.util.Comparator
|
|
+ * @return A positive integer, zero, or a negative integer if the first
|
|
+ * argument is greater than, equal to, or smaller than, respectively, the
|
|
+ * second one.
|
|
+ */
|
|
+ public int compare( long k1, long k2 );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongComparators.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with comparators.
|
|
+ */
|
|
+public class LongComparators {
|
|
+ private LongComparators() {}
|
|
+ /** A type-specific comparator mimicking the natural order. */
|
|
+ protected static class NaturalImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return ( Long.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return NATURAL_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final LongComparator NATURAL_COMPARATOR = new NaturalImplicitComparator();
|
|
+ /** A type-specific comparator mimicking the opposite of the natural order. */
|
|
+ protected static class OppositeImplicitComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return - ( Long.compare((a),(b)) );
|
|
+ }
|
|
+ private Object readResolve() { return OPPOSITE_COMPARATOR; }
|
|
+ };
|
|
+
|
|
+ public static final LongComparator OPPOSITE_COMPARATOR = new OppositeImplicitComparator();
|
|
+ protected static class OppositeComparator extends AbstractLongComparator implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ private final LongComparator comparator;
|
|
+ protected OppositeComparator( final LongComparator c ) {
|
|
+ comparator = c;
|
|
+ }
|
|
+ public final int compare( final long a, final long b ) {
|
|
+ return comparator.compare( b, a );
|
|
+ }
|
|
+ };
|
|
+ /** Returns a comparator representing the opposite order of the given comparator.
|
|
+ *
|
|
+ * @param c a comparator.
|
|
+ * @return a comparator representing the opposite order of <code>c</code>.
|
|
+ */
|
|
+ public static LongComparator oppositeComparator( final LongComparator c ) {
|
|
+ return new OppositeComparator ( c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHash.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+/** A type-specific {@link Hash} interface.
|
|
+ *
|
|
+ * @see Hash
|
|
+ */
|
|
+public interface LongHash {
|
|
+ /** A type-specific hash strategy.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.Hash.Strategy
|
|
+ */
|
|
+ public interface Strategy {
|
|
+ /** Returns the hash code of the specified element with respect to this hash strategy.
|
|
+ *
|
|
+ * @param e an element.
|
|
+ * @return the hash code of the given element with respect to this hash strategy.
|
|
+ */
|
|
+ public int hashCode( long e );
|
|
+ /** Returns true if the given elements are equal with respect to this hash strategy.
|
|
+ *
|
|
+ * @param a an element.
|
|
+ * @param b another element.
|
|
+ * @return true if the two specified elements are equal with respect to this hash strategy.
|
|
+ */
|
|
+ public boolean equals( long a, long b );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongHeaps.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with heaps.
|
|
+ *
|
|
+ * <P>The static methods of this class allow to treat arrays as 0-based heaps. They
|
|
+ * are used in the implementation of heap-based queues, but they may be also used
|
|
+ * directly.
|
|
+ *
|
|
+ */
|
|
+public class LongHeaps {
|
|
+ private LongHeaps() {}
|
|
+ /** Moves the given element down into the heap until it reaches the lowest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved down.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int downHeap( final long[] heap, final int size, int i, final LongComparator c ) {
|
|
+ assert i < size;
|
|
+ final long e = heap[ i ];
|
|
+ int child;
|
|
+ if ( c == null )
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ long t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && ( (heap[ right ]) < (t) ) ) t = heap[ child = right ];
|
|
+ if ( ( (e) <= (t) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ else
|
|
+ while ( ( child = ( i << 1 ) + 1 ) < size ) {
|
|
+ long t = heap[ child ];
|
|
+ final int right = child + 1;
|
|
+ if ( right < size && c.compare( heap[ right ], t ) < 0 ) t = heap[ child = right ];
|
|
+ if ( c.compare( e, t ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = child;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Moves the given element up in the heap until it reaches the highest possible position.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param i the index of the element that must be moved up.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ * @return the new position of the element of index <code>i</code>.
|
|
+ */
|
|
+
|
|
+ public static int upHeap( final long[] heap, final int size, int i, final LongComparator c ) {
|
|
+ assert i < size;
|
|
+ final long e = heap[ i ];
|
|
+ if ( c == null )
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final long t = heap[ parent ];
|
|
+ if ( ( (t) <= (e) ) ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ else
|
|
+ while ( i != 0 ) {
|
|
+ final int parent = ( i - 1 ) >>> 1;
|
|
+ final long t = heap[ parent ];
|
|
+ if ( c.compare( t, e ) <= 0 ) break;
|
|
+ heap[ i ] = t;
|
|
+ i = parent;
|
|
+ }
|
|
+ heap[ i ] = e;
|
|
+ return i;
|
|
+ }
|
|
+ /** Makes an array into a heap.
|
|
+ *
|
|
+ * @param heap the heap (starting at 0).
|
|
+ * @param size the number of elements in the heap.
|
|
+ * @param c a type-specific comparator, or <code>null</code> for the natural order.
|
|
+ */
|
|
+ public static void makeHeap( final long[] heap, final int size, final LongComparator c ) {
|
|
+ int i = size >>> 1;
|
|
+ while( i-- != 0 ) downHeap( heap, size, i, c );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterable.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface LongIterator extends Iterator<Long> {
|
|
+ /**
|
|
+ * Returns the next element as a primitive type.
|
|
+ *
|
|
+ * @return the next element in the iteration.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ long nextLong();
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongIterators.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class LongIterators {
|
|
+ private LongIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator extends AbstractLongListIterator implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public long nextLong() { throw new NoSuchElementException(); }
|
|
+ public long previousLong() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator extends AbstractLongListIterator {
|
|
+ private final long element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static LongListIterator singleton( final long element ) {
|
|
+ return new SingletonIterator ( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator extends AbstractLongListIterator {
|
|
+ private final long[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final long[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static LongListIterator wrap( final long[] array, final int offset, final int length ) {
|
|
+ LongArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator ( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static LongListIterator wrap( final long[] array ) {
|
|
+ return new ArrayIterator ( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final long array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.nextLong();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final long array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+
|
|
+ public static long[] unwrap( final LongIterator i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ long array[] = new long[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = LongArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.nextLong();
|
|
+ }
|
|
+ return LongArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static long[] unwrap( final LongIterator i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int unwrap( final LongIterator i, final LongCollection c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.nextLong() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static long unwrap( final LongIterator i, final LongCollection c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.nextLong() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final LongIterator i, final LongCollection s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.nextLong() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static int pour( final LongIterator i, final LongCollection s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static LongList pour( final LongIterator i, int max ) {
|
|
+ final LongArrayList l = new LongArrayList ();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static LongList pour( final LongIterator i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper extends AbstractLongIterator {
|
|
+ final Iterator<Long> i;
|
|
+ public IteratorWrapper( final Iterator<Long> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public long nextLong() { return ((i.next()).longValue()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static LongIterator asLongIterator( final Iterator i ) {
|
|
+ if ( i instanceof LongIterator ) return (LongIterator )i;
|
|
+ return new IteratorWrapper ( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper extends AbstractLongListIterator {
|
|
+ final ListIterator<Long> i;
|
|
+ public ListIteratorWrapper( final ListIterator<Long> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( long k ) { i.set( (Long.valueOf(k)) ); }
|
|
+ public void add( long k ) { i.add( (Long.valueOf(k)) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public long nextLong() { return ((i.next()).longValue()); }
|
|
+ public long previousLong() { return ((i.previous()).longValue()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ @SuppressWarnings({"unchecked","rawtypes"})
|
|
+ public static LongListIterator asLongIterator( final ListIterator i ) {
|
|
+ if ( i instanceof LongListIterator ) return (LongListIterator )i;
|
|
+ return new ListIteratorWrapper ( i );
|
|
+ }
|
|
+ private static class IntervalIterator extends AbstractLongBidirectionalIterator {
|
|
+ private final long from, to;
|
|
+ long curr;
|
|
+ public IntervalIterator( final long from, final long to ) {
|
|
+ this.from = this.curr = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < to; }
|
|
+ public boolean hasPrevious() { return curr > from; }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return curr++;
|
|
+ }
|
|
+ public long previousLong() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return --curr;
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( curr + n <= to ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = (int)( to - curr );
|
|
+ curr = to;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( curr - n >= from ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = (int)( curr - from );
|
|
+ curr = from;
|
|
+ return n;
|
|
+ }
|
|
+ }
|
|
+ /** Creates a type-specific bidirectional iterator over an interval.
|
|
+ *
|
|
+ * <P>The type-specific bidirectional iterator returned by this method will return the
|
|
+ * elements <code>from</code>, <code>from+1</code>,…, <code>to-1</code>.
|
|
+ *
|
|
+ * <P>Note that all other type-specific interval iterator are <em>list</em>
|
|
+ * iterators. Of course, this is not possible with longs as the index
|
|
+ * returned by {@link java.util.ListIterator#nextIndex() nextIndex()}/{@link
|
|
+ * java.util.ListIterator#previousIndex() previousIndex()} would exceed an integer.
|
|
+ *
|
|
+ * @param from the starting element (inclusive).
|
|
+ * @param to the ending element (exclusive).
|
|
+ * @return a type-specific bidirectional iterator enumerating the elements from <code>from</code> to <code>to</code>.
|
|
+ */
|
|
+ public static LongBidirectionalIterator fromTo( final long from, final long to ) {
|
|
+ return new IntervalIterator( from, to );
|
|
+ }
|
|
+ private static class IteratorConcatenator extends AbstractLongIterator {
|
|
+ final LongIterator a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final LongIterator a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ long next = a[ lastOffset = offset ].nextLong();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static LongIterator concat( final LongIterator a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static LongIterator concat( final LongIterator a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator ( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator extends AbstractLongIterator {
|
|
+ final protected LongIterator i;
|
|
+ public UnmodifiableIterator( final LongIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static LongIterator unmodifiable( final LongIterator i ) { return new UnmodifiableIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator extends AbstractLongBidirectionalIterator {
|
|
+ final protected LongBidirectionalIterator i;
|
|
+ public UnmodifiableBidirectionalIterator( final LongBidirectionalIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ public long previousLong() { return i.previousLong(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static LongBidirectionalIterator unmodifiable( final LongBidirectionalIterator i ) { return new UnmodifiableBidirectionalIterator ( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator extends AbstractLongListIterator {
|
|
+ final protected LongListIterator i;
|
|
+ public UnmodifiableListIterator( final LongListIterator i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public long nextLong() { return i.nextLong(); }
|
|
+ public long previousLong() { return i.previousLong(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long next() { return i.next(); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ @Override
|
|
+ public Long previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static LongListIterator unmodifiable( final LongListIterator i ) { return new UnmodifiableListIterator ( i ); }
|
|
+
|
|
+ /** A wrapper promoting the results of an IntIterator. */
|
|
+ protected static class IntIteratorWrapper implements LongIterator {
|
|
+ final it.unimi.dsi.fastutil.ints.IntIterator iterator;
|
|
+ public IntIteratorWrapper( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
|
|
+ this.iterator = iterator;
|
|
+ }
|
|
+ public boolean hasNext() { return iterator.hasNext(); }
|
|
+ public Long next() { return Long.valueOf( iterator.nextInt() ); }
|
|
+ public long nextLong() { return iterator.nextInt(); }
|
|
+ public void remove() { iterator.remove(); }
|
|
+ public int skip( final int n ) { return iterator.skip( n ); }
|
|
+ }
|
|
+ /** Returns an iterator backed by the specified integer iterator.
|
|
+ * @return an iterator backed by the specified integer iterator.
|
|
+ */
|
|
+ public static LongIterator wrap( final it.unimi.dsi.fastutil.ints.IntIterator iterator ) {
|
|
+ return new IntIteratorWrapper( iterator );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface LongList extends List<Long>, Comparable<List<? extends Long>>, LongCollection {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ LongListIterator iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongListIterator longListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongListIterator longListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ LongListIterator listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ LongListIterator listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongList longSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ LongList subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, long a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, long a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, long a[], int offset, int length );
|
|
+ /**
|
|
+ * @see List#add(Object)
|
|
+ */
|
|
+ boolean add( long key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ void add( int index, long key );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, LongCollection c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( int index, LongList c );
|
|
+ /**
|
|
+ * @see List#add(int,Object)
|
|
+ */
|
|
+ boolean addAll( LongList c );
|
|
+ /**
|
|
+ * @see List#get(int)
|
|
+ */
|
|
+ long getLong( int index );
|
|
+ /**
|
|
+ * @see List#indexOf(Object)
|
|
+ */
|
|
+ int indexOf( long k );
|
|
+ /**
|
|
+ * @see List#lastIndexOf(Object)
|
|
+ */
|
|
+ int lastIndexOf( long k );
|
|
+ /**
|
|
+ * @see List#remove(int)
|
|
+ */
|
|
+ long removeLong( int index );
|
|
+ /**
|
|
+ * @see List#set(int,Object)
|
|
+ */
|
|
+ long set( int index, long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface LongListIterator extends ListIterator<Long>, LongBidirectionalIterator {
|
|
+ void set( long k );
|
|
+ void add( long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongLists.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.List;
|
|
+import java.util.Collection;
|
|
+import java.util.Random;
|
|
+/** A class providing static methods and objects that do useful things with type-specific lists.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongLists {
|
|
+ private LongLists() {}
|
|
+ /** Shuffles the specified list using the specified pseudorandom number generator.
|
|
+ *
|
|
+ * @param l the list to be shuffled.
|
|
+ * @param random a pseudorandom number generator (please use a <a href="http://dsiutils.dsi.unimi.it/docs/it/unimi/dsi/util/XorShiftStarRandom.html">XorShift*</a> generator).
|
|
+ * @return <code>l</code>.
|
|
+ */
|
|
+ public static LongList shuffle( final LongList l, final Random random ) {
|
|
+ for( int i = l.size(); i-- != 0; ) {
|
|
+ final int p = random.nextInt( i + 1 );
|
|
+ final long t = l.getLong( i );
|
|
+ l.set( i, l.getLong( p ) );
|
|
+ l.set( p, t );
|
|
+ }
|
|
+ return l;
|
|
+ }
|
|
+ /** An immutable class representing an empty type-specific list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class EmptyList extends LongCollections.EmptyCollection implements LongList , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyList() {}
|
|
+ public void add( final int index, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long removeLong( int i ) { throw new UnsupportedOperationException(); }
|
|
+ public long set( final int index, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( long k ) { return -1; }
|
|
+ public int lastIndexOf( long k ) { return -1; }
|
|
+ public boolean addAll( Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public Long get( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public boolean addAll( LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( LongList c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( int i, LongList c ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int index, final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean add( final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long set( final int index, final Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long getLong( int i ) { throw new IndexOutOfBoundsException(); }
|
|
+ public Long remove( int k ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( Object k ) { return -1; }
|
|
+ public int lastIndexOf( Object k ) { return -1; }
|
|
+ //SUPPRESS_WARNINGS_KEY_UNCHECKED
|
|
+ //public KEY_ITERATOR KEY_GENERIC iterator( int i ) { if ( i == 0 ) return ITERATORS.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+
|
|
+ public LongIterator longIterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator listIterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator iterator() { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongListIterator listIterator( int i ) { if ( i == 0 ) return LongIterators.EMPTY_ITERATOR; throw new IndexOutOfBoundsException( String.valueOf( i ) ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( int i ) { return listIterator( i ); }
|
|
+ public LongList subList( int from, int to ) { if ( from == 0 && to == 0 ) return this; throw new IndexOutOfBoundsException(); }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( int from, int to ) { return subList( from, to ); }
|
|
+ public void getElements( int from, long[] a, int offset, int length ) { if ( from == 0 && length == 0 && offset >= 0 && offset <= a.length ) return; throw new IndexOutOfBoundsException(); }
|
|
+ public void removeElements( int from, int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( int s ) { throw new UnsupportedOperationException(); }
|
|
+ public int compareTo( final List<? extends Long> o ) {
|
|
+ if ( o == this ) return 0;
|
|
+ return ((List<?>)o).isEmpty() ? 0 : -1;
|
|
+ }
|
|
+ private Object readResolve() { return EMPTY_LIST; }
|
|
+ public Object clone() { return EMPTY_LIST; }
|
|
+ public int hashCode() { return 1; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( Object o ) { return o instanceof List && ((List)o).isEmpty(); }
|
|
+ public String toString() { return "[]"; }
|
|
+ }
|
|
+ /** An empty list (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptyList EMPTY_LIST = new EmptyList();
|
|
+ /** An immutable class representing a type-specific singleton list.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific list.
|
|
+ */
|
|
+ public static class Singleton extends AbstractLongList implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ private final long element;
|
|
+ private Singleton( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public long getLong( final int i ) { if ( i == 0 ) return element; throw new IndexOutOfBoundsException(); }
|
|
+ public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final long k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final Collection <? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public long[] toLongArray() {
|
|
+ long a[] = new long[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public LongListIterator listIterator() { return LongIterators.singleton( element ); }
|
|
+ public LongListIterator iterator() { return listIterator(); }
|
|
+ public LongListIterator listIterator( int i ) {
|
|
+ if ( i > 1 || i < 0 ) throw new IndexOutOfBoundsException();
|
|
+ LongListIterator l = listIterator();
|
|
+ if ( i == 1 ) l.next();
|
|
+ return l;
|
|
+ }
|
|
+
|
|
+ public LongList subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ if ( from != 0 || to != 1 ) return EMPTY_LIST;
|
|
+ return this;
|
|
+ }
|
|
+ public int size() { return 1; }
|
|
+ public void size( final int size ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return this; }
|
|
+ public boolean rem( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int i, final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongList singleton( final long element ) { return new Singleton ( element ); }
|
|
+ /** Returns a type-specific immutable list containing only the specified element. The returned list is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned list.
|
|
+ * @return a type-specific immutable list containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongList singleton( final Object element ) { return new Singleton ( ((((Long)(element)).longValue())) ); }
|
|
+ /** A synchronized wrapper class for lists. */
|
|
+ public static class SynchronizedList extends LongCollections.SynchronizedCollection implements LongList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected SynchronizedList( final LongList l, final Object sync ) {
|
|
+ super( l, sync );
|
|
+ this.list = l;
|
|
+ }
|
|
+ protected SynchronizedList( final LongList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public long getLong( final int i ) { synchronized( sync ) { return list.getLong( i ); } }
|
|
+ public long set( final int i, final long k ) { synchronized( sync ) { return list.set( i, k ); } }
|
|
+ public void add( final int i, final long k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public long removeLong( final int i ) { synchronized( sync ) { return list.removeLong( i ); } }
|
|
+ public int indexOf( final long k ) { synchronized( sync ) { return list.indexOf( k ); } }
|
|
+ public int lastIndexOf( final long k ) { synchronized( sync ) { return list.lastIndexOf( k ); } }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public void getElements( final int from, final long a[], final int offset, final int length ) { synchronized( sync ) { list.getElements( from, a, offset, length ); } }
|
|
+ public void removeElements( final int from, final int to ) { synchronized( sync ) { list.removeElements( from, to ); } }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { synchronized( sync ) { list.addElements( index, a, offset, length ); } }
|
|
+ public void addElements( int index, final long a[] ) { synchronized( sync ) { list.addElements( index, a ); } }
|
|
+ public void size( final int size ) { synchronized( sync ) { list.size( size ); } }
|
|
+ public LongListIterator iterator() { return list.listIterator(); }
|
|
+ public LongListIterator listIterator() { return list.listIterator(); }
|
|
+ public LongListIterator listIterator( final int i ) { return list.listIterator( i ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
|
|
+ public LongList subList( final int from, final int to ) { synchronized( sync ) { return synchronize( list.subList( from, to ), sync ); } }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ public int compareTo( final List<? extends Long> o ) { synchronized( sync ) { return list.compareTo( o ); } }
|
|
+ public boolean addAll( final int index, final LongCollection c ) { synchronized( sync ) { return list.addAll( index, c ); } }
|
|
+ public boolean addAll( final int index, LongList l ) { synchronized( sync ) { return list.addAll( index, l ); } }
|
|
+ public boolean addAll( LongList l ) { synchronized( sync ) { return list.addAll( l ); } }
|
|
+ public Long get( final int i ) { synchronized( sync ) { return list.get( i ); } }
|
|
+ public void add( final int i, Long k ) { synchronized( sync ) { list.add( i, k ); } }
|
|
+ public Long set( final int index, Long k ) { synchronized( sync ) { return list.set( index, k ); } }
|
|
+ public Long remove( final int i ) { synchronized( sync ) { return list.remove( i ); } }
|
|
+ public int indexOf( final Object o ) { synchronized( sync ) { return list.indexOf( o ); } }
|
|
+ public int lastIndexOf( final Object o ) { synchronized( sync ) { return list.lastIndexOf( o ); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static LongList synchronize( final LongList l ) { return new SynchronizedList ( l ); }
|
|
+ /** Returns a synchronized type-specific list backed by the given type-specific list, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param l the list to be wrapped in a synchronized list.
|
|
+ * @param sync an object that will be used to synchronize the access to the list.
|
|
+ * @return a synchronized view of the specified list.
|
|
+ * @see java.util.Collections#synchronizedList(List)
|
|
+ */
|
|
+ public static LongList synchronize( final LongList l, final Object sync ) { return new SynchronizedList ( l, sync ); }
|
|
+ /** An unmodifiable wrapper class for lists. */
|
|
+ public static class UnmodifiableList extends LongCollections.UnmodifiableCollection implements LongList , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongList list; // Due to the large number of methods that are not in COLLECTION, this is worth caching.
|
|
+ protected UnmodifiableList( final LongList l ) {
|
|
+ super( l );
|
|
+ this.list = l;
|
|
+ }
|
|
+ public long getLong( final int i ) { return list.getLong( i ); }
|
|
+ public long set( final int i, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public void add( final int i, final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public long removeLong( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final long k ) { return list.indexOf( k ); }
|
|
+ public int lastIndexOf( final long k ) { return list.lastIndexOf( k ); }
|
|
+ public boolean addAll( final int index, final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void getElements( final int from, final long a[], final int offset, final int length ) { list.getElements( from, a, offset, length ); }
|
|
+ public void removeElements( final int from, final int to ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[], int offset, int length ) { throw new UnsupportedOperationException(); }
|
|
+ public void addElements( int index, final long a[] ) { throw new UnsupportedOperationException(); }
|
|
+ public void size( final int size ) { list.size( size ); }
|
|
+ public LongListIterator iterator() { return listIterator(); }
|
|
+ public LongListIterator listIterator() { return LongIterators.unmodifiable( list.listIterator() ); }
|
|
+ public LongListIterator listIterator( final int i ) { return LongIterators.unmodifiable( list.listIterator( i ) ); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator() { return listIterator(); }
|
|
+ @Deprecated
|
|
+ public LongListIterator longListIterator( final int i ) { return listIterator( i ); }
|
|
+ public LongList subList( final int from, final int to ) { return unmodifiable( list.subList( from, to ) ); }
|
|
+ @Deprecated
|
|
+ public LongList longSubList( final int from, final int to ) { return subList( from, to ); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ public int compareTo( final List<? extends Long> o ) { return list.compareTo( o ); }
|
|
+ public boolean addAll( final int index, final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final LongList l ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final int index, final LongList l ) { throw new UnsupportedOperationException(); }
|
|
+ public Long get( final int i ) { return list.get( i ); }
|
|
+ public void add( final int i, Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long set( final int index, Long k ) { throw new UnsupportedOperationException(); }
|
|
+ public Long remove( final int i ) { throw new UnsupportedOperationException(); }
|
|
+ public int indexOf( final Object o ) { return list.indexOf( o ); }
|
|
+ public int lastIndexOf( final Object o ) { return list.lastIndexOf( o ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific list backed by the given type-specific list.
|
|
+ *
|
|
+ * @param l the list to be wrapped in an unmodifiable list.
|
|
+ * @return an unmodifiable view of the specified list.
|
|
+ * @see java.util.Collections#unmodifiableList(List)
|
|
+ */
|
|
+ public static LongList unmodifiable( final LongList l ) { return new UnmodifiableList ( l ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenCustomHashSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific hash set with a fast, small-footprint implementation whose {@linkplain it.unimi.dsi.fastutil.Hash.Strategy hashing strategy}
|
|
+ * is specified at creation time.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * filled up to a specified <em>load factor</em>, and then doubled in size to
|
|
+ * accommodate new entries. If the table is emptied below <em>one fourth</em>
|
|
+ * of the load factor, it is halved in size. However, halving is
|
|
+ * not performed when deleting entries from an iterator, as it would interfere
|
|
+ * with the iteration process.
|
|
+ *
|
|
+ * <p>Note that {@link #clear()} does not modify the hash table size.
|
|
+ * Rather, a family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class LongOpenCustomHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The hash strategy of this custom set. */
|
|
+ protected it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+
|
|
+ public LongOpenCustomHashSet( final int expected, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this.strategy = strategy;
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final int expected, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Collection<? extends Long> c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongCollection c, final float f, it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c.size(), f, strategy );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongCollection c, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongIterator i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f, strategy );
|
|
+ while( i.hasNext() ) add( i.nextLong() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final LongIterator i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Iterator<?> i, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( LongIterators.asLongIterator( i ), f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final Iterator<?> i, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( LongIterators.asLongIterator( i ), strategy );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( length < 0 ? 0 : length, f, strategy );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final int offset, final int length, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final float f, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, 0, a.length, f, strategy );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param strategy the strategy.
|
|
+ */
|
|
+ public LongOpenCustomHashSet( final long[] a, final it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR, strategy );
|
|
+ }
|
|
+ /** Returns the hashing strategy.
|
|
+ *
|
|
+ * @return the hashing strategy of this custom hash set.
|
|
+ */
|
|
+ public it.unimi.dsi.fastutil.longs.LongHash.Strategy strategy() {
|
|
+ return strategy;
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ int pos;
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ containsNull = true;
|
|
+ key[ n ] = k;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( strategy.equals( (curr), (k) ) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final long k ) {
|
|
+ if ( ( strategy.equals( ( k), (0) ) ) ) return containsNull;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( strategy.equals( (k), (curr) ) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** An iterator over a hash set. */
|
|
+ private class SetIterator extends AbstractLongIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the null key. */
|
|
+ boolean mustReturnNull = LongOpenCustomHashSet.this.containsNull;
|
|
+ /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNull ) {
|
|
+ mustReturnNull = false;
|
|
+ last = n;
|
|
+ return key[ n ];
|
|
+ }
|
|
+ final long key[] = LongOpenCustomHashSet.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ return wrapped.getLong( - pos - 1 );
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = LongOpenCustomHashSet.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(curr) ) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ LongOpenCustomHashSet.this.containsNull = false;
|
|
+ LongOpenCustomHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ LongOpenCustomHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ }
|
|
+ public LongIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(key[ i ]) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ }
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongOpenCustomHashSet clone() {
|
|
+ LongOpenCustomHashSet c;
|
|
+ try {
|
|
+ c = (LongOpenCustomHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ c.strategy = strategy;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += ( strategy.hashCode(key[ i ]) );
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final LongIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ long k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ if ( ( strategy.equals( (k), (0) ) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = ( it.unimi.dsi.fastutil.HashCommon.mix( strategy.hashCode(k) ) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongOpenHashSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.arraySize;
|
|
+import static it.unimi.dsi.fastutil.HashCommon.maxFill;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific hash set with with a fast, small-footprint implementation.
|
|
+ *
|
|
+ * <P>Instances of this class use a hash table to represent a set. The table is
|
|
+ * enlarged as needed by doubling its size when new entries are created, but it is <em>never</em> made
|
|
+ * smaller (even on a {@link #clear()}). A family of {@linkplain #trim() trimming
|
|
+ * methods} lets you control the size of the table; this is particularly useful
|
|
+ * if you reuse instances of this class.
|
|
+ *
|
|
+ * @see Hash
|
|
+ * @see HashCommon
|
|
+ */
|
|
+public class LongOpenHashSet extends AbstractLongSet implements java.io.Serializable, Cloneable, Hash {
|
|
+ private static final long serialVersionUID = 0L;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** The array of keys. */
|
|
+ protected transient long[] key;
|
|
+ /** The mask for wrapping a position counter. */
|
|
+ protected transient int mask;
|
|
+ /** Whether this set contains the null key. */
|
|
+ protected transient boolean containsNull;
|
|
+ /** The current table size. Note that an additional element is allocated for storing the null key. */
|
|
+ protected transient int n;
|
|
+ /** Threshold after which we rehash. It must be the table size times {@link #f}. */
|
|
+ protected transient int maxFill;
|
|
+ /** Number of entries in the set (including the null key, if present). */
|
|
+ protected int size;
|
|
+ /** The acceptable load factor. */
|
|
+ protected final float f;
|
|
+ /** Creates a new hash set.
|
|
+ *
|
|
+ * <p>The actual table size will be the least power of two greater than <code>expected</code>/<code>f</code>.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+
|
|
+ public LongOpenHashSet( final int expected, final float f ) {
|
|
+ if ( f <= 0 || f > 1 ) throw new IllegalArgumentException( "Load factor must be greater than 0 and smaller than or equal to 1" );
|
|
+ if ( expected < 0 ) throw new IllegalArgumentException( "The expected number of elements must be nonnegative" );
|
|
+ this.f = f;
|
|
+ n = arraySize( expected, f );
|
|
+ mask = n - 1;
|
|
+ maxFill = maxFill( n, f );
|
|
+ key = new long[ n + 1 ];
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ *
|
|
+ * @param expected the expected number of elements in the hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final int expected ) {
|
|
+ this( expected, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set with initial expected {@link Hash#DEFAULT_INITIAL_SIZE} elements
|
|
+ * and {@link Hash#DEFAULT_LOAD_FACTOR} as load factor.
|
|
+ */
|
|
+ public LongOpenHashSet() {
|
|
+ this( DEFAULT_INITIAL_SIZE, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final Collection<? extends Long> c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given collection.
|
|
+ *
|
|
+ * @param c a {@link Collection} to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final Collection<? extends Long> c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongCollection c, final float f ) {
|
|
+ this( c.size(), f );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongCollection c ) {
|
|
+ this( c, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongIterator i, final float f ) {
|
|
+ this( DEFAULT_INITIAL_SIZE, f );
|
|
+ while( i.hasNext() ) add( i.nextLong() );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by a type-specific iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator whose elements will fill the set.
|
|
+ */
|
|
+ public LongOpenHashSet( final LongIterator i ) {
|
|
+ this( i, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final Iterator<?> i, final float f ) {
|
|
+ this( LongIterators.asLongIterator( i ), f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor using elements provided by an iterator.
|
|
+ *
|
|
+ * @param i an iterator whose elements will fill the set.
|
|
+ */
|
|
+ public LongOpenHashSet( final Iterator<?> i ) {
|
|
+ this( LongIterators.asLongIterator( i ) );
|
|
+ }
|
|
+ /** Creates a new hash set and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final int offset, final int length, final float f ) {
|
|
+ this( length < 0 ? 0 : length, f );
|
|
+ LongArrays.ensureOffsetLength( a, offset, length );
|
|
+ for( int i = 0; i < length; i++ ) add( a[ offset + i ] );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the set.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final int offset, final int length ) {
|
|
+ this( a, offset, length, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ /** Creates a new hash set copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ * @param f the load factor.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a, final float f ) {
|
|
+ this( a, 0, a.length, f );
|
|
+ }
|
|
+ /** Creates a new hash set with {@link Hash#DEFAULT_LOAD_FACTOR} as load factor
|
|
+ * copying the elements of an array.
|
|
+ *
|
|
+ * @param a an array to be copied into the new hash set.
|
|
+ */
|
|
+ public LongOpenHashSet( final long[] a ) {
|
|
+ this( a, DEFAULT_LOAD_FACTOR );
|
|
+ }
|
|
+ private int realSize() {
|
|
+ return containsNull ? size - 1 : size;
|
|
+ }
|
|
+ private void ensureCapacity( final int capacity ) {
|
|
+ final int needed = arraySize( capacity, f );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ private void tryCapacity( final long capacity ) {
|
|
+ final int needed = (int)Math.min( 1 << 30, Math.max( 2, HashCommon.nextPowerOfTwo( (long)Math.ceil( capacity / f ) ) ) );
|
|
+ if ( needed > n ) rehash( needed );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( LongCollection c ) {
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ /** {@inheritDoc} */
|
|
+ public boolean addAll( Collection<? extends Long> c ) {
|
|
+ // The resulting collection will be at least c.size() big
|
|
+ if ( f <= .5 ) ensureCapacity( c.size() ); // The resulting collection will be sized for c.size() elements
|
|
+ else tryCapacity( size() + c.size() ); // The resulting collection will be tentatively sized for size() + c.size() elements
|
|
+ return super.addAll( c );
|
|
+ }
|
|
+ public boolean add( final long k ) {
|
|
+ int pos;
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return false;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ // The starting point.
|
|
+ if ( ! ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) {
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ while( ! ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) )
|
|
+ if ( ( (curr) == (k) ) ) return false;
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( size++ >= maxFill ) rehash( arraySize( size + 1, f ) );
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ return true;
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ protected final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ private boolean removeEntry( final int pos ) {
|
|
+ size--;
|
|
+ shiftKeys( pos );
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+ private boolean removeNullEntry() {
|
|
+ containsNull = false;
|
|
+ key[ n ] = (0);
|
|
+ size--;
|
|
+ if ( size < maxFill / 4 && n > DEFAULT_INITIAL_SIZE ) rehash( n / 2 );
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ public boolean remove( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ if ( containsNull ) return removeNullEntry();
|
|
+ return false;
|
|
+ }
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return removeEntry( pos );
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public boolean contains( final long k ) {
|
|
+ if ( ( (k) == (0) ) ) return containsNull;
|
|
+ long curr;
|
|
+ final long[] key = this.key;
|
|
+ int pos;
|
|
+ // The starting point.
|
|
+ if ( ( (curr = key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ while( true ) {
|
|
+ if ( ( (curr = key[ pos = ( pos + 1 ) & mask ]) == (0) ) ) return false;
|
|
+ if ( ( (k) == (curr) ) ) return true;
|
|
+ }
|
|
+ }
|
|
+ /* Removes all elements from this set.
|
|
+ *
|
|
+ * <P>To increase object reuse, this method does not change the table size.
|
|
+ * If you want to reduce the table size, you must use {@link #trim()}.
|
|
+ *
|
|
+ */
|
|
+ public void clear() {
|
|
+ if ( size == 0 ) return;
|
|
+ size = 0;
|
|
+ containsNull = false;
|
|
+ Arrays.fill( key, (0) );
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** A no-op for backward compatibility.
|
|
+ *
|
|
+ * @param growthFactor unused.
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public void growthFactor( int growthFactor ) {}
|
|
+ /** Gets the growth factor (2).
|
|
+ *
|
|
+ * @return the growth factor of this set, which is fixed (2).
|
|
+ * @see #growthFactor(int)
|
|
+ * @deprecated Since <code>fastutil</code> 6.1.0, hash tables are doubled when they are too full.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public int growthFactor() {
|
|
+ return 16;
|
|
+ }
|
|
+ /** An iterator over a hash set. */
|
|
+ private class SetIterator extends AbstractLongIterator {
|
|
+ /** The index of the last entry returned, if positive or zero; initially, {@link #n}. If negative, the last
|
|
+ element returned was that of index {@code - pos - 1} from the {@link #wrapped} list. */
|
|
+ int pos = n;
|
|
+ /** The index of the last entry that has been returned (more precisely, the value of {@link #pos} if {@link #pos} is positive,
|
|
+ or {@link Integer#MIN_VALUE} if {@link #pos} is negative). It is -1 if either
|
|
+ we did not return an entry yet, or the last returned entry has been removed. */
|
|
+ int last = -1;
|
|
+ /** A downward counter measuring how many entries must still be returned. */
|
|
+ int c = size;
|
|
+ /** A boolean telling us whether we should return the null key. */
|
|
+ boolean mustReturnNull = LongOpenHashSet.this.containsNull;
|
|
+ /** A lazily allocated list containing elements that have wrapped around the table because of removals. */
|
|
+ LongArrayList wrapped;
|
|
+ public boolean hasNext() {
|
|
+ return c != 0;
|
|
+ }
|
|
+ public long nextLong() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ c--;
|
|
+ if ( mustReturnNull ) {
|
|
+ mustReturnNull = false;
|
|
+ last = n;
|
|
+ return key[ n ];
|
|
+ }
|
|
+ final long key[] = LongOpenHashSet.this.key;
|
|
+ for(;;) {
|
|
+ if ( --pos < 0 ) {
|
|
+ // We are just enumerating elements from the wrapped list.
|
|
+ last = Integer.MIN_VALUE;
|
|
+ return wrapped.getLong( - pos - 1 );
|
|
+ }
|
|
+ if ( ! ( (key[ pos ]) == (0) ) ) return key[ last = pos ];
|
|
+ }
|
|
+ }
|
|
+ /** Shifts left entries with the specified hash code, starting at the specified position,
|
|
+ * and empties the resulting free entry.
|
|
+ *
|
|
+ * @param pos a starting position.
|
|
+ */
|
|
+ private final void shiftKeys( int pos ) {
|
|
+ // Shift entries with the same hash.
|
|
+ int last, slot;
|
|
+ long curr;
|
|
+ final long[] key = LongOpenHashSet.this.key;
|
|
+ for(;;) {
|
|
+ pos = ( ( last = pos ) + 1 ) & mask;
|
|
+ for(;;) {
|
|
+ if ( ( (curr = key[ pos ]) == (0) ) ) {
|
|
+ key[ last ] = (0);
|
|
+ return;
|
|
+ }
|
|
+ slot = (int)it.unimi.dsi.fastutil.HashCommon.mix( (curr) ) & mask;
|
|
+ if ( last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos ) break;
|
|
+ pos = ( pos + 1 ) & mask;
|
|
+ }
|
|
+ if ( pos < last ) { // Wrapped entry.
|
|
+ if ( wrapped == null ) wrapped = new LongArrayList ( 2 );
|
|
+ wrapped.add( key[ pos ] );
|
|
+ }
|
|
+ key[ last ] = curr;
|
|
+ }
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ if ( last == n ) {
|
|
+ LongOpenHashSet.this.containsNull = false;
|
|
+ LongOpenHashSet.this.key[ n ] = (0);
|
|
+ }
|
|
+ else if ( pos >= 0 ) shiftKeys( last );
|
|
+ else {
|
|
+ // We're removing wrapped entries.
|
|
+ LongOpenHashSet.this.remove( wrapped.getLong( - pos - 1 ) );
|
|
+ last = -1; // Note that we must not decrement size
|
|
+ return;
|
|
+ }
|
|
+ size--;
|
|
+ last = -1; // You can no longer remove this entry.
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ }
|
|
+ public LongIterator iterator() {
|
|
+ return new SetIterator();
|
|
+ }
|
|
+ /** A no-op for backward compatibility. The kind of tables implemented by
|
|
+ * this class never need rehashing.
|
|
+ *
|
|
+ * <P>If you need to reduce the table size to fit exactly
|
|
+ * this set, use {@link #trim()}.
|
|
+ *
|
|
+ * @return true.
|
|
+ * @see #trim()
|
|
+ * @deprecated A no-op.
|
|
+ */
|
|
+ @Deprecated
|
|
+ public boolean rehash() {
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set, making the table as small as possible.
|
|
+ *
|
|
+ * <P>This method rehashes the table to the smallest size satisfying the
|
|
+ * load factor. It can be used when the set will not be changed anymore, so
|
|
+ * to optimize access speed and size.
|
|
+ *
|
|
+ * <P>If the table size is already the minimum possible, this method
|
|
+ * does nothing.
|
|
+ *
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim(int)
|
|
+ */
|
|
+ public boolean trim() {
|
|
+ final int l = arraySize( size, f );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch(OutOfMemoryError cantDoIt) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes this set if the table is too large.
|
|
+ *
|
|
+ * <P>Let <var>N</var> be the smallest table size that can hold
|
|
+ * <code>max(n,{@link #size()})</code> entries, still satisfying the load factor. If the current
|
|
+ * table size is smaller than or equal to <var>N</var>, this method does
|
|
+ * nothing. Otherwise, it rehashes this set in a table of size
|
|
+ * <var>N</var>.
|
|
+ *
|
|
+ * <P>This method is useful when reusing sets. {@linkplain #clear() Clearing a
|
|
+ * set} leaves the table size untouched. If you are reusing a set
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large table just
|
|
+ * because of a few large transient sets.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ * @return true if there was enough memory to trim the set.
|
|
+ * @see #trim()
|
|
+ */
|
|
+ public boolean trim( final int n ) {
|
|
+ final int l = HashCommon.nextPowerOfTwo( (int)Math.ceil( n / f ) );
|
|
+ if ( l >= n || size > maxFill( l, f ) ) return true;
|
|
+ try {
|
|
+ rehash( l );
|
|
+ }
|
|
+ catch( OutOfMemoryError cantDoIt ) { return false; }
|
|
+ return true;
|
|
+ }
|
|
+ /** Rehashes the set.
|
|
+ *
|
|
+ * <P>This method implements the basic rehashing strategy, and may be
|
|
+ * overriden by subclasses implementing different rehashing strategies (e.g.,
|
|
+ * disk-based rehashing). However, you should not override this method
|
|
+ * unless you understand the internal workings of this class.
|
|
+ *
|
|
+ * @param newN the new size
|
|
+ */
|
|
+
|
|
+ protected void rehash( final int newN ) {
|
|
+ final long key[] = this.key;
|
|
+ final int mask = newN - 1; // Note that this is used by the hashing macro
|
|
+ final long newKey[] = new long[ newN + 1 ];
|
|
+ int i = n, pos;
|
|
+ for( int j = realSize(); j-- != 0; ) {
|
|
+ while( ( (key[ --i ]) == (0) ) );
|
|
+ if ( ! ( (newKey[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (key[ i ]) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (newKey[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ newKey[ pos ] = key[ i ];
|
|
+ }
|
|
+ n = newN;
|
|
+ this.mask = mask;
|
|
+ maxFill = maxFill( n, f );
|
|
+ this.key = newKey;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+
|
|
+ public LongOpenHashSet clone() {
|
|
+ LongOpenHashSet c;
|
|
+ try {
|
|
+ c = (LongOpenHashSet )super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.key = key.clone();
|
|
+ c.containsNull = containsNull;
|
|
+ return c;
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * This method overrides the generic method provided by the superclass.
|
|
+ * Since <code>equals()</code> is not overriden, it is important
|
|
+ * that the value returned by this method is the same value as
|
|
+ * the one returned by the overriden method.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0;
|
|
+ for( int j = realSize(), i = 0; j-- != 0; ) {
|
|
+ while( ( (key[ i ]) == (0) ) ) i++;
|
|
+ h += it.unimi.dsi.fastutil.HashCommon.long2int(key[ i ]);
|
|
+ i++;
|
|
+ }
|
|
+ // Zero / null have hash zero.
|
|
+ return h;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ final LongIterator i = iterator();
|
|
+ s.defaultWriteObject();
|
|
+ for( int j = size; j-- != 0; ) s.writeLong( i.nextLong() );
|
|
+ }
|
|
+
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ n = arraySize( size, f );
|
|
+ maxFill = maxFill( n, f );
|
|
+ mask = n - 1;
|
|
+ final long key[] = this.key = new long[ n + 1 ];
|
|
+ long k;
|
|
+ for( int i = size, pos; i-- != 0; ) {
|
|
+ k = s.readLong();
|
|
+ if ( ( (k) == (0) ) ) {
|
|
+ pos = n;
|
|
+ containsNull = true;
|
|
+ }
|
|
+ else {
|
|
+ if ( ! ( (key[ pos = (int)it.unimi.dsi.fastutil.HashCommon.mix( (k) ) & mask ]) == (0) ) )
|
|
+ while ( ! ( (key[ pos = ( pos + 1 ) & mask ]) == (0) ) );
|
|
+ }
|
|
+ key[ pos ] = k;
|
|
+ }
|
|
+ if ( ASSERTS ) checkTable();
|
|
+ }
|
|
+ private void checkTable() {}
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueue.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Paolo Boldi and Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.NoSuchElementException;
|
|
+import it.unimi.dsi.fastutil.PriorityQueue;
|
|
+/** A type-specific {@link PriorityQueue}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #comparator()}.
|
|
+ */
|
|
+public interface LongPriorityQueue extends PriorityQueue<Long> {
|
|
+ /** Enqueues a new element.
|
|
+ *
|
|
+ * @param x the element to enqueue.
|
|
+ */
|
|
+ void enqueue( long x );
|
|
+ /** Dequeues the {@linkplain #first() first} element from the queue.
|
|
+ *
|
|
+ * @return the dequeued element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long dequeueLong();
|
|
+ /** Returns the first element of the queue.
|
|
+ *
|
|
+ * @return the first element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long firstLong();
|
|
+ /** Returns the last element of the queue, that is, the element the would be dequeued last (optional operation).
|
|
+ *
|
|
+ * @return the last element.
|
|
+ * @throws NoSuchElementException if the queue is empty.
|
|
+ */
|
|
+ long lastLong();
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link PriorityQueue#comparator()}.
|
|
+ *
|
|
+ * @see PriorityQueue#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongPriorityQueues.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+/** A class providing static methods and objects that do useful things with type-specific priority queues.
|
|
+ *
|
|
+ * @see it.unimi.dsi.fastutil.PriorityQueue
|
|
+ */
|
|
+public class LongPriorityQueues {
|
|
+ private LongPriorityQueues() {}
|
|
+ /** A synchronized wrapper class for priority queues. */
|
|
+ public static class SynchronizedPriorityQueue implements LongPriorityQueue {
|
|
+ final protected LongPriorityQueue q;
|
|
+ final protected Object sync;
|
|
+ protected SynchronizedPriorityQueue( final LongPriorityQueue q, final Object sync ) {
|
|
+ this.q = q;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedPriorityQueue( final LongPriorityQueue q ) {
|
|
+ this.q = q;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public void enqueue( long x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public long dequeueLong() { synchronized( sync ) { return q.dequeueLong(); } }
|
|
+ public long firstLong() { synchronized( sync ) { return q.firstLong(); } }
|
|
+ public long lastLong() { synchronized( sync ) { return q.lastLong(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return q.isEmpty(); } }
|
|
+ public int size() { synchronized( sync ) { return q.size(); } }
|
|
+ public void clear() { synchronized( sync ) { q.clear(); } }
|
|
+ public void changed() { synchronized( sync ) { q.changed(); } }
|
|
+ public LongComparator comparator() { synchronized( sync ) { return q.comparator(); } }
|
|
+ public void enqueue( Long x ) { synchronized( sync ) { q.enqueue( x ); } }
|
|
+ public Long dequeue() { synchronized( sync ) { return q.dequeue(); } }
|
|
+ public Long first() { synchronized( sync ) { return q.first(); } }
|
|
+ public Long last() { synchronized( sync ) { return q.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static LongPriorityQueue synchronize( final LongPriorityQueue q ) { return new SynchronizedPriorityQueue( q ); }
|
|
+ /** Returns a synchronized type-specific priority queue backed by the specified type-specific priority queue, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param q the priority queue to be wrapped in a synchronized priority queue.
|
|
+ * @param sync an object that will be used to synchronize the access to the priority queue.
|
|
+ * @return a synchronized view of the specified priority queue.
|
|
+ */
|
|
+ public static LongPriorityQueue synchronize( final LongPriorityQueue q, final Object sync ) { return new SynchronizedPriorityQueue( q, sync ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface LongSet extends LongCollection , Set<Long> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ LongIterator iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( long k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongSets {
|
|
+ private LongSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet extends LongCollections.EmptyCollection implements LongSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton extends AbstractLongSet implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final long element;
|
|
+ protected Singleton( final long element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final long k ) { return ( (k) == (element) ); }
|
|
+ public boolean addAll( final Collection<? extends Long> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ /* Slightly optimized w.r.t. the one in ABSTRACT_SET. */
|
|
+ public long[] toLongArray() {
|
|
+ long a[] = new long[ 1 ];
|
|
+ a[ 0 ] = element;
|
|
+ return a;
|
|
+ }
|
|
+ public boolean addAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final LongCollection c ) { throw new UnsupportedOperationException(); }
|
|
+ public LongListIterator iterator() { return LongIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSet singleton( final long element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSet singleton( final Long element ) {
|
|
+ return new Singleton ( ((element).longValue()) );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet extends LongCollections.SynchronizedCollection implements LongSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final LongSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final LongSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final long k ) { synchronized( sync ) { return collection.remove( (Long.valueOf(k)) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static LongSet synchronize( final LongSet s ) { return new SynchronizedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static LongSet synchronize( final LongSet s, final Object sync ) { return new SynchronizedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet extends LongCollections.UnmodifiableCollection implements LongSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final LongSet s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final long k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static LongSet unmodifiable( final LongSet s ) { return new UnmodifiableSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface LongSortedSet extends LongSet , SortedSet<Long> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ LongBidirectionalIterator iterator( long fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ LongBidirectionalIterator longIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ LongBidirectionalIterator iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ LongSortedSet subSet( Long fromElement, Long toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ LongSortedSet headSet( Long toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ LongSortedSet tailSet( Long fromElement );
|
|
+ /** Returns the comparator associated with this sorted set, or null if it uses its elements' natural ordering.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#comparator()}.
|
|
+ *
|
|
+ * @see SortedSet#comparator()
|
|
+ */
|
|
+ LongComparator comparator();
|
|
+ /**
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ LongSortedSet subSet( long fromElement, long toElement) ;
|
|
+ /**
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ LongSortedSet headSet( long toElement );
|
|
+ /**
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ LongSortedSet tailSet( long fromElement );
|
|
+ /**
|
|
+ * @see SortedSet#first()
|
|
+ */
|
|
+ long firstLong();
|
|
+ /**
|
|
+ * @see SortedSet#last()
|
|
+ */
|
|
+ long lastLong();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongSortedSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class LongSortedSets {
|
|
+ private LongSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet extends LongSets.EmptySet implements LongSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( long ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return iterator(); }
|
|
+
|
|
+ public LongBidirectionalIterator iterator( long from ) { return LongIterators.EMPTY_ITERATOR; }
|
|
+
|
|
+ public LongSortedSet subSet( long from, long to ) { return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet headSet( long from ) { return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet tailSet( long to ) { return EMPTY_SET; }
|
|
+ public long firstLong() { throw new NoSuchElementException(); }
|
|
+ public long lastLong() { throw new NoSuchElementException(); }
|
|
+ public LongComparator comparator() { return null; }
|
|
+ public LongSortedSet subSet( Long from, Long to ) { return EMPTY_SET; }
|
|
+ public LongSortedSet headSet( Long from ) { return EMPTY_SET; }
|
|
+ public LongSortedSet tailSet( Long to ) { return EMPTY_SET; }
|
|
+ public Long first() { throw new NoSuchElementException(); }
|
|
+ public Long last() { throw new NoSuchElementException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton extends LongSets.Singleton implements LongSortedSet , java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final LongComparator comparator;
|
|
+ private Singleton( final long element, final LongComparator comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final long element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+
|
|
+ final int compare( final long k1, final long k2 ) {
|
|
+ return comparator == null ? ( Long.compare((k1),(k2)) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public LongBidirectionalIterator iterator( long from ) {
|
|
+ LongBidirectionalIterator i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public LongComparator comparator() { return comparator; }
|
|
+
|
|
+ public LongSortedSet subSet( final long from, final long to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet headSet( final long to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+
|
|
+ public LongSortedSet tailSet( final long from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public long firstLong() { return element; }
|
|
+ public long lastLong() { return element; }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long first() { return (Long.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public Long last() { return (Long.valueOf(element)); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return subSet( ((from).longValue()), ((to).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet headSet( final Long to ) { return headSet( ((to).longValue()) ); }
|
|
+ /** {@inheritDoc}
|
|
+ * @deprecated Please use the corresponding type-specific method instead. */
|
|
+ @Deprecated
|
|
+ public LongSortedSet tailSet( final Long from ) { return tailSet( ((from).longValue()) ); }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final long element ) {
|
|
+ return new Singleton ( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final long element, final LongComparator comparator ) {
|
|
+ return new Singleton ( element, comparator );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final Object element ) {
|
|
+ return new Singleton( ((((Long)(element)).longValue())) );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static LongSortedSet singleton( final Object element, final LongComparator comparator ) {
|
|
+ return new Singleton( ((((Long)(element)).longValue())), comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet extends LongSets.SynchronizedSet implements LongSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongSortedSet sortedSet;
|
|
+ protected SynchronizedSortedSet( final LongSortedSet s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final LongSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public LongComparator comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return new SynchronizedSortedSet ( sortedSet.subSet( from, to ), sync ); }
|
|
+ public LongSortedSet headSet( final long to ) { return new SynchronizedSortedSet ( sortedSet.headSet( to ), sync ); }
|
|
+ public LongSortedSet tailSet( final long from ) { return new SynchronizedSortedSet ( sortedSet.tailSet( from ), sync ); }
|
|
+ public LongBidirectionalIterator iterator() { return sortedSet.iterator(); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return sortedSet.iterator(); }
|
|
+ public long firstLong() { synchronized( sync ) { return sortedSet.firstLong(); } }
|
|
+ public long lastLong() { synchronized( sync ) { return sortedSet.lastLong(); } }
|
|
+ public Long first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public Long last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return new SynchronizedSortedSet( sortedSet.subSet( from, to ), sync ); }
|
|
+ public LongSortedSet headSet( final Long to ) { return new SynchronizedSortedSet( sortedSet.headSet( to ), sync ); }
|
|
+ public LongSortedSet tailSet( final Long from ) { return new SynchronizedSortedSet( sortedSet.tailSet( from ), sync ); }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet synchronize( final LongSortedSet s ) { return new SynchronizedSortedSet ( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet synchronize( final LongSortedSet s, final Object sync ) { return new SynchronizedSortedSet ( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet extends LongSets.UnmodifiableSet implements LongSortedSet , java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final LongSortedSet sortedSet;
|
|
+ protected UnmodifiableSortedSet( final LongSortedSet s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public LongComparator comparator() { return sortedSet.comparator(); }
|
|
+ public LongSortedSet subSet( final long from, final long to ) { return new UnmodifiableSortedSet ( sortedSet.subSet( from, to ) ); }
|
|
+ public LongSortedSet headSet( final long to ) { return new UnmodifiableSortedSet ( sortedSet.headSet( to ) ); }
|
|
+ public LongSortedSet tailSet( final long from ) { return new UnmodifiableSortedSet ( sortedSet.tailSet( from ) ); }
|
|
+ public LongBidirectionalIterator iterator() { return LongIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public LongBidirectionalIterator iterator( final long from ) { return LongIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public LongBidirectionalIterator longIterator() { return iterator(); }
|
|
+ public long firstLong() { return sortedSet.firstLong(); }
|
|
+ public long lastLong() { return sortedSet.lastLong(); }
|
|
+ public Long first() { return sortedSet.first(); }
|
|
+ public Long last() { return sortedSet.last(); }
|
|
+ public LongSortedSet subSet( final Long from, final Long to ) { return new UnmodifiableSortedSet( sortedSet.subSet( from, to ) ); }
|
|
+ public LongSortedSet headSet( final Long to ) { return new UnmodifiableSortedSet( sortedSet.headSet( to ) ); }
|
|
+ public LongSortedSet tailSet( final Long from ) { return new UnmodifiableSortedSet( sortedSet.tailSet( from ) ); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static LongSortedSet unmodifiable( final LongSortedSet s ) { return new UnmodifiableSortedSet ( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/LongStack.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Primitive-type-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.longs;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+/** A type-specific {@link Stack}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ */
|
|
+public interface LongStack extends Stack<Long> {
|
|
+ /**
|
|
+ * @see Stack#push(Object)
|
|
+ */
|
|
+ void push( long k );
|
|
+ /**
|
|
+ * @see Stack#pop()
|
|
+ */
|
|
+ long popLong();
|
|
+ /**
|
|
+ * @see Stack#top()
|
|
+ */
|
|
+ long topLong();
|
|
+ /**
|
|
+ * @see Stack#peek(int)
|
|
+ */
|
|
+ long peekLong( int i );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/longs/package.html b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/longs/package.html
|
|
@@ -0,0 +0,0 @@
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
+<html>
|
|
+ <head>
|
|
+ <title>fastutil</title>
|
|
+ </head>
|
|
+
|
|
+ <body>
|
|
+
|
|
+ <P>Provides type-specific classes for long elements or keys.
|
|
+
|
|
+ </body>
|
|
+</html>
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain it.unimi.dsi.fastutil.BidirectionalIterator bidirectional iterators}.
|
|
+ *
|
|
+ * <P>To create a type-specific bidirectional iterator, besides what is needed
|
|
+ * for an iterator you need both a method returning the previous element as
|
|
+ * primitive type and a method returning the previous element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #back(int)} that
|
|
+ * uses type-specific methods.
|
|
+ */
|
|
+public abstract class AbstractObjectBidirectionalIterator <K> extends AbstractObjectIterator <K> implements ObjectBidirectionalIterator <K> {
|
|
+ protected AbstractObjectBidirectionalIterator() {}
|
|
+ /** This method just iterates the type-specific version of {@link #previous()} for
|
|
+ * at most <code>n</code> times, stopping if {@link
|
|
+ * #hasPrevious()} becomes false. */
|
|
+ public int back( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasPrevious() ) previous();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.AbstractCollection;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+/** An abstract class providing basic methods for collections implementing a type-specific interface.
|
|
+ *
|
|
+ * <P>In particular, this class provide {@link #iterator()}, <code>add()</code>, {@link #remove(Object)} and
|
|
+ * {@link #contains(Object)} methods that just call the type-specific counterpart.
|
|
+ */
|
|
+public abstract class AbstractObjectCollection <K> extends AbstractCollection<K> implements ObjectCollection <K> {
|
|
+ protected AbstractObjectCollection() {}
|
|
+ public Object[] toArray() {
|
|
+ final Object[] a = new Object[ size() ];
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ return a;
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public <T> T[] toArray( T[] a ) {
|
|
+ final int size = size();
|
|
+ if ( a.length < size ) a = (T[])java.lang.reflect.Array.newInstance( a.getClass().getComponentType(), size );
|
|
+ it.unimi.dsi.fastutil.objects.ObjectIterators.unwrap( iterator(), a );
|
|
+ if ( size < a.length ) a[ size ] = null;
|
|
+ return a;
|
|
+ }
|
|
+ /** Adds all elements of the given collection to this collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean addAll( Collection<? extends K> c ) {
|
|
+ boolean retVal = false;
|
|
+ final Iterator<? extends K> i = c.iterator();
|
|
+ int n = c.size();
|
|
+ while( n-- != 0 ) if ( add( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean add( K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract ObjectIterator <K> iterator();
|
|
+ /** Checks whether this collection contains all elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection contains all elements of the argument.
|
|
+ */
|
|
+ public boolean containsAll( Collection<?> c ) {
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( ! contains( i.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Retains in this collection only elements from the given collection.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean retainAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = size();
|
|
+ final Iterator<?> i = iterator();
|
|
+ while( n-- != 0 ) {
|
|
+ if ( ! c.contains( i.next() ) ) {
|
|
+ i.remove();
|
|
+ retVal = true;
|
|
+ }
|
|
+ }
|
|
+ return retVal;
|
|
+ }
|
|
+ /** Remove from this collection all elements in the given collection.
|
|
+ * If the collection is an instance of this class, it uses faster iterators.
|
|
+ *
|
|
+ * @param c a collection.
|
|
+ * @return <code>true</code> if this collection changed as a result of the call.
|
|
+ */
|
|
+ public boolean removeAll( Collection<?> c ) {
|
|
+ boolean retVal = false;
|
|
+ int n = c.size();
|
|
+ final Iterator<?> i = c.iterator();
|
|
+ while( n-- != 0 ) if ( remove( i.next() ) ) retVal = true;
|
|
+ return retVal;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size() == 0;
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator <K> i = iterator();
|
|
+ int n = size();
|
|
+ Object k;
|
|
+ boolean first = true;
|
|
+ s.append("{");
|
|
+ while(n-- != 0) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.next();
|
|
+ if (this == k) s.append("(this collection)"); else
|
|
+ s.append(String.valueOf(k));
|
|
+ }
|
|
+ s.append("}");
|
|
+ return s.toString();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific iterators.
|
|
+ *
|
|
+ * <P>To create a type-specific iterator you need both a method returning the
|
|
+ * next element as primitive type and a method returning the next element as an
|
|
+ * object. However, if you inherit from this class you need just one (anyone).
|
|
+ *
|
|
+ * <P>This class implements also a trivial version of {@link #skip(int)} that uses
|
|
+ * type-specific methods; moreover, {@link #remove()} will throw an {@link
|
|
+ * UnsupportedOperationException}.
|
|
+ *
|
|
+ * @see java.util.Iterator
|
|
+ */
|
|
+public abstract class AbstractObjectIterator <K> implements ObjectIterator <K> {
|
|
+ protected AbstractObjectIterator() {}
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void remove() { throw new UnsupportedOperationException(); }
|
|
+ /** This method just iterates the type-specific version of {@link #next()} for at most
|
|
+ * <code>n</code> times, stopping if {@link #hasNext()} becomes false.*/
|
|
+ public int skip( final int n ) {
|
|
+ int i = n;
|
|
+ while( i-- != 0 && hasNext() ) next();
|
|
+ return n - i - 1;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.Stack;
|
|
+import java.util.List;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** An abstract class providing basic methods for lists implementing a type-specific list interface.
|
|
+ *
|
|
+ * <P>As an additional bonus, this class implements on top of the list operations a type-specific stack.
|
|
+ */
|
|
+public abstract class AbstractObjectList <K> extends AbstractObjectCollection <K> implements ObjectList <K>, Stack <K> {
|
|
+ protected AbstractObjectList() {}
|
|
+ /** Ensures that the given index is nonnegative and not greater than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or greater than the list size.
|
|
+ */
|
|
+ protected void ensureIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index > size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ /** Ensures that the given index is nonnegative and smaller than the list size.
|
|
+ *
|
|
+ * @param index an index.
|
|
+ * @throws IndexOutOfBoundsException if the given index is negative or not smaller than the list size.
|
|
+ */
|
|
+ protected void ensureRestrictedIndex( final int index ) {
|
|
+ if ( index < 0 ) throw new IndexOutOfBoundsException( "Index (" + index + ") is negative" );
|
|
+ if ( index >= size() ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + ( size() ) + ")" );
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ add( size(), k );
|
|
+ return true;
|
|
+ }
|
|
+ public K remove( int i ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public K set( final int index, final K k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+ public boolean addAll( int index, final Collection<? extends K> c ) {
|
|
+ ensureIndex( index );
|
|
+ int n = c.size();
|
|
+ if ( n == 0 ) return false;
|
|
+ Iterator<? extends K> i = c.iterator();
|
|
+ while( n-- != 0 ) add( index++, i.next() );
|
|
+ return true;
|
|
+ }
|
|
+ /** Delegates to a more generic method. */
|
|
+ public boolean addAll( final Collection<? extends K> c ) {
|
|
+ return addAll( size(), c );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectListIterator <K> objectListIterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectListIterator <K> objectListIterator( final int index ) {
|
|
+ return listIterator( index );
|
|
+ }
|
|
+ public ObjectListIterator <K> iterator() {
|
|
+ return listIterator();
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator() {
|
|
+ return listIterator( 0 );
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < AbstractObjectList.this.size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = pos++ ); }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return AbstractObjectList.this.get( last = --pos ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ AbstractObjectList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractObjectList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ AbstractObjectList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return indexOf( k ) >= 0;
|
|
+ }
|
|
+ public int indexOf( final Object k ) {
|
|
+ final ObjectListIterator <K> i = listIterator();
|
|
+ K e;
|
|
+ while( i.hasNext() ) {
|
|
+ e = i.next();
|
|
+ if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.previousIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final Object k ) {
|
|
+ ObjectListIterator <K> i = listIterator( size() );
|
|
+ K e;
|
|
+ while( i.hasPrevious() ) {
|
|
+ e = i.previous();
|
|
+ if ( ( (k) == null ? (e) == null : (k).equals(e) ) ) return i.nextIndex();
|
|
+ }
|
|
+ return -1;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ int i = size();
|
|
+ if ( size > i ) while( i++ < size ) add( (null) );
|
|
+ else while( i-- != size ) remove( i );
|
|
+ }
|
|
+ public ObjectList <K> subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IndexOutOfBoundsException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new ObjectSubList <K>( this, from, to );
|
|
+ }
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectList <K> objectSubList( final int from, final int to ) {
|
|
+ return subList( from, to );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( to );
|
|
+ ObjectListIterator <K> i = listIterator( from );
|
|
+ int n = to - from;
|
|
+ if ( n < 0 ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ while( n-- != 0 ) {
|
|
+ i.next();
|
|
+ i.remove();
|
|
+ }
|
|
+ }
|
|
+ /** Adds elements to this type-specific list one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( int index, final K a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ while( length-- != 0 ) add( index++, a[ offset++ ] );
|
|
+ }
|
|
+ public void addElements( final int index, final K a[] ) {
|
|
+ addElements( index, a, 0, a.length );
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array one-by-one.
|
|
+ *
|
|
+ * <P>This is a trivial iterator-based implementation. It is expected that
|
|
+ * implementations will override this method with a more optimized version.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final Object a[], int offset, int length ) {
|
|
+ ObjectListIterator <K> i = listIterator( from );
|
|
+ if ( offset < 0 ) throw new ArrayIndexOutOfBoundsException( "Offset (" + offset + ") is negative" );
|
|
+ if ( offset + length > a.length ) throw new ArrayIndexOutOfBoundsException( "End index (" + ( offset + length ) + ") is greater than array length (" + a.length + ")" );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + ( from + length ) + ") is greater than list size (" + size() + ")" );
|
|
+ while( length-- != 0 ) a[ offset++ ] = i.next();
|
|
+ }
|
|
+ private boolean valEquals( final Object a, final Object b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof List ) ) return false;
|
|
+ final List<?> l = (List<?>)o;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final ListIterator<?> i1 = listIterator(), i2 = l.listIterator();
|
|
+ while( s-- != 0 ) if ( ! valEquals( i1.next(), i2.next() ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this list to another object. If the
|
|
+ * argument is a {@link java.util.List}, this method performs a lexicographical comparison; otherwise,
|
|
+ * it throws a <code>ClassCastException</code>.
|
|
+ *
|
|
+ * @param l a list.
|
|
+ * @return if the argument is a {@link java.util.List}, a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ * @throws ClassCastException if the argument is not a list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public int compareTo( final List<? extends K> l ) {
|
|
+ if ( l == this ) return 0;
|
|
+ if ( l instanceof ObjectList ) {
|
|
+ final ObjectListIterator <K> i1 = listIterator(), i2 = ((ObjectList <K>)l).listIterator();
|
|
+ int r;
|
|
+ K e1, e2;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ e1 = i1.next();
|
|
+ e2 = i2.next();
|
|
+ if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ ListIterator<? extends K> i1 = listIterator(), i2 = l.listIterator();
|
|
+ int r;
|
|
+ while( i1.hasNext() && i2.hasNext() ) {
|
|
+ if ( ( r = ((Comparable<? super K>)i1.next()).compareTo( i2.next() ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i2.hasNext() ? -1 : ( i1.hasNext() ? 1 : 0 );
|
|
+ }
|
|
+ /** Returns the hash code for this list, which is identical to {@link java.util.List#hashCode()}.
|
|
+ *
|
|
+ * @return the hash code for this list.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ ObjectIterator <K> i = iterator();
|
|
+ int h = 1, s = size();
|
|
+ while ( s-- != 0 ) {
|
|
+ K k = i.next();
|
|
+ h = 31 * h + ( (k) == null ? 0 : (k).hashCode() );
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public void push( K o ) {
|
|
+ add( o );
|
|
+ }
|
|
+ public K pop() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return remove( size() - 1 );
|
|
+ }
|
|
+ public K top() {
|
|
+ if ( isEmpty() ) throw new NoSuchElementException();
|
|
+ return get( size() - 1 );
|
|
+ }
|
|
+ public K peek( int i ) {
|
|
+ return get( size() - 1 - i );
|
|
+ }
|
|
+ public String toString() {
|
|
+ final StringBuilder s = new StringBuilder();
|
|
+ final ObjectIterator <K> i = iterator();
|
|
+ int n = size();
|
|
+ K k;
|
|
+ boolean first = true;
|
|
+ s.append("[");
|
|
+ while( n-- != 0 ) {
|
|
+ if (first) first = false;
|
|
+ else s.append(", ");
|
|
+ k = i.next();
|
|
+ if (this == k) s.append("(this list)"); else
|
|
+ s.append( String.valueOf( k ) );
|
|
+ }
|
|
+ s.append("]");
|
|
+ return s.toString();
|
|
+ }
|
|
+ public static class ObjectSubList <K> extends AbstractObjectList <K> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ /** The list this sublist restricts. */
|
|
+ protected final ObjectList <K> l;
|
|
+ /** Initial (inclusive) index of this sublist. */
|
|
+ protected final int from;
|
|
+ /** Final (exclusive) index of this sublist. */
|
|
+ protected int to;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ public ObjectSubList( final ObjectList <K> l, final int from, final int to ) {
|
|
+ this.l = l;
|
|
+ this.from = from;
|
|
+ this.to = to;
|
|
+ }
|
|
+ private void assertRange() {
|
|
+ if ( ASSERTS ) {
|
|
+ assert from <= l.size();
|
|
+ assert to <= l.size();
|
|
+ assert to >= from;
|
|
+ }
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ l.add( to, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ return true;
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ ensureIndex( index );
|
|
+ l.add( from + index, k );
|
|
+ to++;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public boolean addAll( final int index, final Collection<? extends K> c ) {
|
|
+ ensureIndex( index );
|
|
+ to += c.size();
|
|
+ if ( ASSERTS ) {
|
|
+ boolean retVal = l.addAll( from + index, c );
|
|
+ assertRange();
|
|
+ return retVal;
|
|
+ }
|
|
+ return l.addAll( from + index, c );
|
|
+ }
|
|
+ public K get( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.get( from + index );
|
|
+ }
|
|
+ public K remove( int index ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ to--;
|
|
+ return l.remove( from + index );
|
|
+ }
|
|
+ public K set( int index, K k ) {
|
|
+ ensureRestrictedIndex( index );
|
|
+ return l.set( from + index, k );
|
|
+ }
|
|
+ public void clear() {
|
|
+ removeElements( 0, size() );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public int size() {
|
|
+ return to - from;
|
|
+ }
|
|
+ public void getElements( final int from, final Object[] a, final int offset, final int length ) {
|
|
+ ensureIndex( from );
|
|
+ if ( from + length > size() ) throw new IndexOutOfBoundsException( "End index (" + from + length + ") is greater than list size (" + size() + ")" );
|
|
+ l.getElements( this.from + from, a, offset, length );
|
|
+ }
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ l.removeElements( this.from + from, this.from + to );
|
|
+ this.to -= ( to - from );
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void addElements( int index, final K a[], int offset, int length ) {
|
|
+ ensureIndex( index );
|
|
+ l.addElements( this.from + index, a, offset, length );
|
|
+ this.to += length;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size(); }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return l.get( from + ( last = pos++ ) ); }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return l.get( from + ( last = --pos ) ); }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectSubList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ if ( ASSERTS ) assertRange();
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectList <K> subList( final int from, final int to ) {
|
|
+ ensureIndex( from );
|
|
+ ensureIndex( to );
|
|
+ if ( from > to ) throw new IllegalArgumentException( "Start index (" + from + ") is greater than end index (" + to + ")" );
|
|
+ return new ObjectSubList <K>( this, from, to );
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ int index = indexOf( o );
|
|
+ if ( index == -1 ) return false;
|
|
+ remove( index );
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class facilitating the creation of type-specific {@linkplain java.util.ListIterator list iterators}.
|
|
+ *
|
|
+ * <P>This class provides trivial type-specific implementations of {@link
|
|
+ * java.util.ListIterator#set(Object) set()} and {@link java.util.ListIterator#add(Object) add()} which
|
|
+ * throw an {@link UnsupportedOperationException}. For primitive types, it also
|
|
+ * provides a trivial implementation of {@link java.util.ListIterator#set(Object) set()} and {@link
|
|
+ * java.util.ListIterator#add(Object) add()} that just invokes the type-specific one.
|
|
+ *
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ */
|
|
+public abstract class AbstractObjectListIterator <K> extends AbstractObjectBidirectionalIterator <K> implements ObjectListIterator <K> {
|
|
+ protected AbstractObjectListIterator() {}
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void set( K k ) { throw new UnsupportedOperationException(); }
|
|
+ /** This method just throws an {@link UnsupportedOperationException}. */
|
|
+ public void add( K k ) { throw new UnsupportedOperationException(); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Set;
|
|
+/** An abstract class providing basic methods for sets implementing a type-specific interface. */
|
|
+public abstract class AbstractObjectSet <K> extends AbstractObjectCollection <K> implements Cloneable, ObjectSet <K> {
|
|
+ protected AbstractObjectSet() {}
|
|
+ public abstract ObjectIterator <K> iterator();
|
|
+ public boolean equals( final Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( !( o instanceof Set ) ) return false;
|
|
+ Set<?> s = (Set<?>) o;
|
|
+ if ( s.size() != size() ) return false;
|
|
+ return containsAll(s);
|
|
+ }
|
|
+ /** Returns a hash code for this set.
|
|
+ *
|
|
+ * The hash code of a set is computed by summing the hash codes of
|
|
+ * its elements.
|
|
+ *
|
|
+ * @return a hash code for this set.
|
|
+ */
|
|
+ public int hashCode() {
|
|
+ int h = 0, n = size();
|
|
+ ObjectIterator <K> i = iterator();
|
|
+ K k;
|
|
+ while( n-- != 0 ) {
|
|
+ k = i.next(); // We need k because KEY2JAVAHASH() is a macro with repeated evaluation.
|
|
+ h += ( (k) == null ? 0 : (k).hashCode() );
|
|
+ }
|
|
+ return h;
|
|
+ }
|
|
+ public boolean remove( Object k ) {
|
|
+ throw new UnsupportedOperationException();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/AbstractObjectSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2003-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+/** An abstract class providing basic methods for sorted sets implementing a type-specific interface. */
|
|
+public abstract class AbstractObjectSortedSet <K> extends AbstractObjectSet <K> implements ObjectSortedSet <K> {
|
|
+ protected AbstractObjectSortedSet() {}
|
|
+ /** Delegates to the new covariantly stronger generic method. */
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public abstract ObjectBidirectionalIterator <K> iterator();
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrayList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Arrays;
|
|
+import java.util.Collection;
|
|
+import java.util.Iterator;
|
|
+import java.util.RandomAccess;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A type-specific array-based list; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>This class implements a lightweight, fast, open, optimized,
|
|
+ * reuse-oriented version of array-based lists. Instances of this class
|
|
+ * represent a list with an array that is enlarged as needed when new entries
|
|
+ * are created (by doubling the current length), but is
|
|
+ * <em>never</em> made smaller (even on a {@link #clear()}). A family of
|
|
+ * {@linkplain #trim() trimming methods} lets you control the size of the
|
|
+ * backing array; this is particularly useful if you reuse instances of this class.
|
|
+ * Range checks are equivalent to those of {@link java.util}'s classes, but
|
|
+ * they are delayed as much as possible.
|
|
+ *
|
|
+ * <p>The backing array is exposed by the {@link #elements()} method. If an instance
|
|
+ * of this class was created {@linkplain #wrap(Object[],int) by wrapping},
|
|
+ * backing-array reallocations will be performed using reflection, so that
|
|
+ * {@link #elements()} can return an array of the same type of the original array: the comments
|
|
+ * about efficiency made in {@link it.unimi.dsi.fastutil.objects.ObjectArrays} apply here.
|
|
+ * Moreover, you must take into consideration that assignment to an array
|
|
+ * not of type {@code Object[]} is slower due to type checking.
|
|
+ *
|
|
+ * <p>This class implements the bulk methods <code>removeElements()</code>,
|
|
+ * <code>addElements()</code> and <code>getElements()</code> using
|
|
+ * high-performance system calls (e.g., {@link
|
|
+ * System#arraycopy(Object,int,Object,int,int) System.arraycopy()} instead of
|
|
+ * expensive loops.
|
|
+ *
|
|
+ * @see java.util.ArrayList
|
|
+ */
|
|
+public class ObjectArrayList <K> extends AbstractObjectList <K> implements RandomAccess, Cloneable, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353131L;
|
|
+ /** The initial default capacity of an array list. */
|
|
+ public final static int DEFAULT_INITIAL_CAPACITY = 16;
|
|
+ /** Whether the backing array was passed to <code>wrap()</code>. In
|
|
+ * this case, we must reallocate with the same type of array. */
|
|
+ protected final boolean wrapped;
|
|
+ /** The backing array. */
|
|
+ protected transient K a[];
|
|
+ /** The current actual size of the list (never greater than the backing-array length). */
|
|
+ protected int size;
|
|
+ private static final boolean ASSERTS = false;
|
|
+ /** Creates a new array list using a given array.
|
|
+ *
|
|
+ * <P>This constructor is only meant to be used by the wrapping methods.
|
|
+ *
|
|
+ * @param a the array that will be used to back this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unused")
|
|
+ protected ObjectArrayList( final K a[], boolean dummy ) {
|
|
+ this.a = a;
|
|
+ this.wrapped = true;
|
|
+ }
|
|
+ /** Creates a new array list with given capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity of the array list (may be 0).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectArrayList( final int capacity ) {
|
|
+ if ( capacity < 0 ) throw new IllegalArgumentException( "Initial capacity (" + capacity + ") is negative" );
|
|
+ a = (K[]) new Object[ capacity ];
|
|
+ wrapped = false;
|
|
+ }
|
|
+ /** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity.
|
|
+ */
|
|
+ public ObjectArrayList() {
|
|
+ this( DEFAULT_INITIAL_CAPACITY );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given collection.
|
|
+ *
|
|
+ * @param c a collection that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final Collection<? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ size = ObjectIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific collection.
|
|
+ *
|
|
+ * @param c a type-specific collection that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectCollection <? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ size = ObjectIterators.unwrap( c.iterator(), a );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with a given type-specific list.
|
|
+ *
|
|
+ * @param l a type-specific list that will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectList <? extends K> l ) {
|
|
+ this( l.size() );
|
|
+ l.getElements( 0, a, 0, size = l.size() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final K a[] ) {
|
|
+ this( a, 0, a.length );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements of a given array.
|
|
+ *
|
|
+ * @param a an array whose elements will be used to fill the array list.
|
|
+ * @param offset the first element to use.
|
|
+ * @param length the number of elements to use.
|
|
+ */
|
|
+ public ObjectArrayList( final K a[], final int offset, final int length ) {
|
|
+ this( length );
|
|
+ System.arraycopy( a, offset, this.a, 0, length );
|
|
+ size = length;
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by an iterator..
|
|
+ *
|
|
+ * @param i an iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final Iterator<? extends K> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Creates a new array list and fills it with the elements returned by a type-specific iterator..
|
|
+ *
|
|
+ * @param i a type-specific iterator whose returned elements will fill the array list.
|
|
+ */
|
|
+ public ObjectArrayList( final ObjectIterator <? extends K> i ) {
|
|
+ this();
|
|
+ while( i.hasNext() ) this.add( i.next() );
|
|
+ }
|
|
+ /** Returns the backing array of this list.
|
|
+ *
|
|
+ * <P>If this array list was created by wrapping a given array, it is guaranteed
|
|
+ * that the type of the returned array will be the same. Otherwise, the returned
|
|
+ * array will be of type {@link Object Object[]} (in spite of the declared return type).
|
|
+ *
|
|
+ * <P><strong>Warning</strong>: This behaviour may cause (unfathomable)
|
|
+ * run-time errors if a method expects an array
|
|
+ * actually of type <code>K[]</code>, but this methods returns an array
|
|
+ * of type {@link Object Object[]}.
|
|
+ *
|
|
+ * @return the backing array.
|
|
+ */
|
|
+ public K[] elements() {
|
|
+ return a;
|
|
+ }
|
|
+ /** Wraps a given array into an array list of given size.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @param length the length of the resulting array list.
|
|
+ * @return a new array list of the given size, wrapping the given array.
|
|
+ */
|
|
+ public static <K> ObjectArrayList <K> wrap( final K a[], final int length ) {
|
|
+ if ( length > a.length ) throw new IllegalArgumentException( "The specified length (" + length + ") is greater than the array size (" + a.length + ")" );
|
|
+ final ObjectArrayList <K> l = new ObjectArrayList <K>( a, false );
|
|
+ l.size = length;
|
|
+ return l;
|
|
+ }
|
|
+ /** Wraps a given array into an array list.
|
|
+ *
|
|
+ * <P>Note it is guaranteed
|
|
+ * that the type of the array returned by {@link #elements()} will be the same
|
|
+ * (see the comments in the class documentation).
|
|
+ *
|
|
+ * @param a an array to wrap.
|
|
+ * @return a new array list wrapping the given array.
|
|
+ */
|
|
+ public static <K> ObjectArrayList <K> wrap( final K a[] ) {
|
|
+ return wrap( a, a.length );
|
|
+ }
|
|
+ /** Ensures that this array list can contain the given number of entries without resizing.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public void ensureCapacity( final int capacity ) {
|
|
+ if ( wrapped ) a = ObjectArrays.ensureCapacity( a, capacity, size );
|
|
+ else {
|
|
+ if ( capacity > a.length ) {
|
|
+ final Object t[] = new Object[ capacity ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = (K[])t;
|
|
+ }
|
|
+ }
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Grows this array list, ensuring that it can contain the given number of entries without resizing,
|
|
+ * and in case enlarging it at least by a factor of two.
|
|
+ *
|
|
+ * @param capacity the new minimum capacity for this array list.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void grow( final int capacity ) {
|
|
+ if ( wrapped ) a = ObjectArrays.grow( a, capacity, size );
|
|
+ else {
|
|
+ if ( capacity > a.length ) {
|
|
+ final int newLength = (int)Math.max( Math.min( 2L * a.length, it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE ), capacity );
|
|
+ final Object t[] = new Object[ newLength ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = (K[])t;
|
|
+ }
|
|
+ }
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public void add( final int index, final K k ) {
|
|
+ ensureIndex( index );
|
|
+ grow( size + 1 );
|
|
+ if ( index != size ) System.arraycopy( a, index, a, index + 1, size - index );
|
|
+ a[ index ] = k;
|
|
+ size++;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public boolean add( final K k ) {
|
|
+ grow( size + 1 );
|
|
+ a[ size++ ] = k;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public K get( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ return a[ index ];
|
|
+ }
|
|
+ public int indexOf( final Object k ) {
|
|
+ for( int i = 0; i < size; i++ ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public int lastIndexOf( final Object k ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (k) == null ? (a[ i ]) == null : (k).equals(a[ i ]) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ public K remove( final int index ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ final K old = a[ index ];
|
|
+ size--;
|
|
+ if ( index != size ) System.arraycopy( a, index + 1, a, index, size - index );
|
|
+ a[ size ] = null;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return old;
|
|
+ }
|
|
+ public boolean rem( final Object k ) {
|
|
+ int index = indexOf( k );
|
|
+ if ( index == -1 ) return false;
|
|
+ remove( index );
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ return true;
|
|
+ }
|
|
+ public boolean remove( final Object o ) {
|
|
+ return rem( o );
|
|
+ }
|
|
+ public K set( final int index, final K k ) {
|
|
+ if ( index >= size ) throw new IndexOutOfBoundsException( "Index (" + index + ") is greater than or equal to list size (" + size + ")" );
|
|
+ K old = a[ index ];
|
|
+ a[ index ] = k;
|
|
+ return old;
|
|
+ }
|
|
+ public void clear() {
|
|
+ Arrays.fill( a, 0, size, null );
|
|
+ size = 0;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ public void size( final int size ) {
|
|
+ if ( size > a.length ) ensureCapacity( size );
|
|
+ if ( size > this.size ) Arrays.fill( a, this.size, size, (null) );
|
|
+ else Arrays.fill( a, size, this.size, (null) );
|
|
+ this.size = size;
|
|
+ }
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Trims this array list so that the capacity is equal to the size.
|
|
+ *
|
|
+ * @see java.util.ArrayList#trimToSize()
|
|
+ */
|
|
+ public void trim() {
|
|
+ trim( 0 );
|
|
+ }
|
|
+ /** Trims the backing array if it is too large.
|
|
+ *
|
|
+ * If the current array length is smaller than or equal to
|
|
+ * <code>n</code>, this method does nothing. Otherwise, it trims the
|
|
+ * array length to the maximum between <code>n</code> and {@link #size()}.
|
|
+ *
|
|
+ * <P>This method is useful when reusing lists. {@linkplain #clear() Clearing a
|
|
+ * list} leaves the array length untouched. If you are reusing a list
|
|
+ * many times, you can call this method with a typical
|
|
+ * size to avoid keeping around a very large array just
|
|
+ * because of a few large transient lists.
|
|
+ *
|
|
+ * @param n the threshold for the trimming.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public void trim( final int n ) {
|
|
+ // TODO: use Arrays.trim() and preserve type only if necessary
|
|
+ if ( n >= a.length || size == a.length ) return;
|
|
+ final K t[] = (K[]) new Object[ Math.max( n, size ) ];
|
|
+ System.arraycopy( a, 0, t, 0, size );
|
|
+ a = t;
|
|
+ if ( ASSERTS ) assert size <= a.length;
|
|
+ }
|
|
+ /** Copies element of this type-specific list into the given array using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ public void getElements( final int from, final Object[] a, final int offset, final int length ) {
|
|
+ ObjectArrays.ensureOffsetLength( a, offset, length );
|
|
+ System.arraycopy( this.a, from, a, offset, length );
|
|
+ }
|
|
+ /** Removes elements of this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ public void removeElements( final int from, final int to ) {
|
|
+ it.unimi.dsi.fastutil.Arrays.ensureFromTo( size, from, to );
|
|
+ System.arraycopy( a, to, a, from, size - to );
|
|
+ size -= ( to - from );
|
|
+ int i = to - from;
|
|
+ while( i-- != 0 ) a[ size + i ] = null;
|
|
+ }
|
|
+ /** Adds elements to this type-specific list using optimized system calls.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ public void addElements( final int index, final K a[], final int offset, final int length ) {
|
|
+ ensureIndex( index );
|
|
+ ObjectArrays.ensureOffsetLength( a, offset, length );
|
|
+ grow( size + length );
|
|
+ System.arraycopy( this.a, index, this.a, index + length, size - index );
|
|
+ System.arraycopy( a, offset, this.a, index, length );
|
|
+ size += length;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean removeAll( final Collection<?> c ) {
|
|
+ final Object[] a = this.a;
|
|
+ int j = 0;
|
|
+ for( int i = 0; i < size; i++ )
|
|
+ if ( ! c.contains( a[ i ] ) ) a[ j++ ] = a[ i ];
|
|
+ Arrays.fill( a, j, size, null );
|
|
+ final boolean modified = size != j;
|
|
+ size = j;
|
|
+ return modified;
|
|
+ }
|
|
+ public ObjectListIterator <K> listIterator( final int index ) {
|
|
+ ensureIndex( index );
|
|
+ return new AbstractObjectListIterator <K>() {
|
|
+ int pos = index, last = -1;
|
|
+ public boolean hasNext() { return pos < size; }
|
|
+ public boolean hasPrevious() { return pos > 0; }
|
|
+ public K next() { if ( ! hasNext() ) throw new NoSuchElementException(); return a[ last = pos++ ]; }
|
|
+ public K previous() { if ( ! hasPrevious() ) throw new NoSuchElementException(); return a[ last = --pos ]; }
|
|
+ public int nextIndex() { return pos; }
|
|
+ public int previousIndex() { return pos - 1; }
|
|
+ public void add( K k ) {
|
|
+ ObjectArrayList.this.add( pos++, k );
|
|
+ last = -1;
|
|
+ }
|
|
+ public void set( K k ) {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectArrayList.this.set( last, k );
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( last == -1 ) throw new IllegalStateException();
|
|
+ ObjectArrayList.this.remove( last );
|
|
+ /* If the last operation was a next(), we are removing an element *before* us, and we must decrease pos correspondingly. */
|
|
+ if ( last < pos ) pos--;
|
|
+ last = -1;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public ObjectArrayList <K> clone() {
|
|
+ ObjectArrayList <K> c = new ObjectArrayList <K>( size );
|
|
+ System.arraycopy( a, 0, c.a, 0, size );
|
|
+ c.size = size;
|
|
+ return c;
|
|
+ }
|
|
+ private boolean valEquals( final K a, final K b ) {
|
|
+ return a == null ? b == null : a.equals( b );
|
|
+ }
|
|
+ /** Compares this type-specific array list to another one.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l a type-specific array list.
|
|
+ * @return true if the argument contains the same elements of this type-specific array list.
|
|
+ */
|
|
+ public boolean equals( final ObjectArrayList <K> l ) {
|
|
+ if ( l == this ) return true;
|
|
+ int s = size();
|
|
+ if ( s != l.size() ) return false;
|
|
+ final K[] a1 = a;
|
|
+ final K[] a2 = l.a;
|
|
+ while( s-- != 0 ) if ( ! valEquals( a1[ s ], a2[ s ] ) ) return false;
|
|
+ return true;
|
|
+ }
|
|
+ /** Compares this array list to another array list.
|
|
+ *
|
|
+ * <P>This method exists only for sake of efficiency. The implementation
|
|
+ * inherited from the abstract implementation would already work.
|
|
+ *
|
|
+ * @param l an array list.
|
|
+ * @return a negative integer,
|
|
+ * zero, or a positive integer as this list is lexicographically less than, equal
|
|
+ * to, or greater than the argument.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public int compareTo( final ObjectArrayList <? extends K> l ) {
|
|
+ final int s1 = size(), s2 = l.size();
|
|
+ final K a1[] = a, a2[] = l.a;
|
|
+ K e1, e2;
|
|
+ int r, i;
|
|
+ for( i = 0; i < s1 && i < s2; i++ ) {
|
|
+ e1 = a1[ i ];
|
|
+ e2 = a2[ i ];
|
|
+ if ( ( r = ( ((Comparable<K>)(e1)).compareTo(e2) ) ) != 0 ) return r;
|
|
+ }
|
|
+ return i < s2 ? -1 : ( i < s1 ? 1 : 0 );
|
|
+ }
|
|
+ private void writeObject( java.io.ObjectOutputStream s ) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private void readObject( java.io.ObjectInputStream s ) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = (K[]) new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = (K) s.readObject();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArraySet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2007-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A simple, brute-force implementation of a set based on a backing array.
|
|
+ *
|
|
+ * <p>The main purpose of this
|
|
+ * implementation is that of wrapping cleanly the brute-force approach to the storage of a very
|
|
+ * small number of items: just put them into an array and scan linearly to find an item.
|
|
+ */
|
|
+public class ObjectArraySet <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = 1L;
|
|
+ /** The backing array (valid up to {@link #size}, excluded). */
|
|
+ private transient Object[] a;
|
|
+ /** The number of valid entries in {@link #a}. */
|
|
+ private int size;
|
|
+ /** Creates a new array set using the given backing array. The resulting set will have as many elements as the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ */
|
|
+ public ObjectArraySet( final Object[] a ) {
|
|
+ this.a = a;
|
|
+ size = a.length;
|
|
+ }
|
|
+ /** Creates a new empty array set.
|
|
+ */
|
|
+ public ObjectArraySet() {
|
|
+ this.a = ObjectArrays.EMPTY_ARRAY;
|
|
+ }
|
|
+ /** Creates a new empty array set of given initial capacity.
|
|
+ *
|
|
+ * @param capacity the initial capacity.
|
|
+ */
|
|
+ public ObjectArraySet( final int capacity ) {
|
|
+ this.a = new Object[ capacity ];
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given collection.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public ObjectArraySet( ObjectCollection <K> c ) {
|
|
+ this( c.size () );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set copying the contents of a given set.
|
|
+ * @param c a collection.
|
|
+ */
|
|
+ public ObjectArraySet( final Collection<? extends K> c ) {
|
|
+ this( c.size() );
|
|
+ addAll( c );
|
|
+ }
|
|
+ /** Creates a new array set using the given backing array and the given number of elements of the array.
|
|
+ *
|
|
+ * <p>It is responsibility of the caller that the first <code>size</code> elements of <code>a</code> are distinct.
|
|
+ *
|
|
+ * @param a the backing array.
|
|
+ * @param size the number of valid elements in <code>a</code>.
|
|
+ */
|
|
+ public ObjectArraySet( final Object[] a, final int size ) {
|
|
+ this.a = a;
|
|
+ this.size = size;
|
|
+ if ( size > a.length ) throw new IllegalArgumentException( "The provided size (" + size + ") is larger than or equal to the array size (" + a.length + ")" );
|
|
+ }
|
|
+ private int findKey( final Object o ) {
|
|
+ for( int i = size; i-- != 0; ) if ( ( (a[ i ]) == null ? (o) == null : (a[ i ]).equals(o) ) ) return i;
|
|
+ return -1;
|
|
+ }
|
|
+ @Override
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectIterator <K> iterator() {
|
|
+ return new AbstractObjectIterator <K> () {
|
|
+ int next = 0;
|
|
+ public boolean hasNext() {
|
|
+ return next < size;
|
|
+ }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return (K) a[ next++ ];
|
|
+ }
|
|
+ public void remove() {
|
|
+ final int tail = size-- - next--;
|
|
+ System.arraycopy( a, next + 1, a, next, tail );
|
|
+ a[ size ] = null;
|
|
+ }
|
|
+ };
|
|
+ }
|
|
+ public boolean contains( final Object k ) {
|
|
+ return findKey( k ) != -1;
|
|
+ }
|
|
+ public int size() {
|
|
+ return size;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean remove( final Object k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos == -1 ) return false;
|
|
+ final int tail = size - pos - 1;
|
|
+ for( int i = 0; i < tail; i++ ) a[ pos + i ] = a[ pos + i + 1 ];
|
|
+ size--;
|
|
+ a[ size ] = null;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean add( final K k ) {
|
|
+ final int pos = findKey( k );
|
|
+ if ( pos != -1 ) return false;
|
|
+ if ( size == a.length ) {
|
|
+ final Object[] b = new Object[ size == 0 ? 2 : size * 2 ];
|
|
+ for( int i = size; i-- != 0; ) b[ i ] = a[ i ];
|
|
+ a = b;
|
|
+ }
|
|
+ a[ size++ ] = k;
|
|
+ return true;
|
|
+ }
|
|
+ @Override
|
|
+ public void clear() {
|
|
+ for( int i = size; i-- != 0; ) a[ i ] = null;
|
|
+ size = 0;
|
|
+ }
|
|
+ @Override
|
|
+ public boolean isEmpty() {
|
|
+ return size == 0;
|
|
+ }
|
|
+ /** Returns a deep copy of this set.
|
|
+ *
|
|
+ * <P>This method performs a deep copy of this hash set; the data stored in the
|
|
+ * set, however, is not cloned. Note that this makes a difference only for object keys.
|
|
+ *
|
|
+ * @return a deep copy of this set.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectArraySet <K> clone() {
|
|
+ ObjectArraySet <K> c;
|
|
+ try {
|
|
+ c = (ObjectArraySet <K>)super.clone();
|
|
+ }
|
|
+ catch(CloneNotSupportedException cantHappen) {
|
|
+ throw new InternalError();
|
|
+ }
|
|
+ c.a = a.clone();
|
|
+ return c;
|
|
+ }
|
|
+ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
|
|
+ s.defaultWriteObject();
|
|
+ for( int i = 0; i < size; i++ ) s.writeObject( a[ i ] );
|
|
+ }
|
|
+ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
|
|
+ s.defaultReadObject();
|
|
+ a = new Object[ size ];
|
|
+ for( int i = 0; i < size; i++ ) a[ i ] = s.readObject();
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectArrays.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ *
|
|
+ *
|
|
+ *
|
|
+ * For the sorting and binary search code:
|
|
+ *
|
|
+ * Copyright (C) 1999 CERN - European Organization for Nuclear Research.
|
|
+ *
|
|
+ * Permission to use, copy, modify, distribute and sell this software and
|
|
+ * its documentation for any purpose is hereby granted without fee,
|
|
+ * provided that the above copyright notice appear in all copies and that
|
|
+ * both that copyright notice and this permission notice appear in
|
|
+ * supporting documentation. CERN makes no representations about the
|
|
+ * suitability of this software for any purpose. It is provided "as is"
|
|
+ * without expressed or implied warranty.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.Arrays;
|
|
+import it.unimi.dsi.fastutil.Hash;
|
|
+import java.util.Random;
|
|
+import java.util.concurrent.ForkJoinPool;
|
|
+import java.util.concurrent.RecursiveAction;
|
|
+import it.unimi.dsi.fastutil.ints.IntArrays;
|
|
+import java.util.Comparator;
|
|
+/** A class providing static methods and objects that do useful things with type-specific arrays.
|
|
+ *
|
|
+ * In particular, the <code>ensureCapacity()</code>, <code>grow()</code>,
|
|
+ * <code>trim()</code> and <code>setLength()</code> methods allow to handle
|
|
+ * arrays much like array lists. This can be very useful when efficiency (or
|
|
+ * syntactic simplicity) reasons make array lists unsuitable.
|
|
+ *
|
|
+ * <P><strong>Warning:</strong> if your array is not of type {@code Object[]},
|
|
+ * {@link #ensureCapacity(Object[],int,int)} and {@link #grow(Object[],int,int)}
|
|
+ * will use {@linkplain java.lang.reflect.Array#newInstance(Class,int) reflection}
|
|
+ * to preserve your array type. Reflection is <em>significantly slower</em> than using <code>new</code>.
|
|
+ * This phenomenon is particularly
|
|
+ * evident in the first growth phases of an array reallocated with doubling (or similar) logic.
|
|
+ *
|
|
+ * <h2>Sorting</h2>
|
|
+ *
|
|
+ * <p>There are several sorting methods available. The main theme is that of letting you choose
|
|
+ * the sorting algorithm you prefer (i.e., trading stability of mergesort for no memory allocation in quicksort).
|
|
+ * Several algorithms provide a parallel version, that will use the {@linkplain Runtime#availableProcessors() number of cores available}.
|
|
+ *
|
|
+ * <p>All comparison-based algorithm have an implementation based on a type-specific comparator.
|
|
+ *
|
|
+ * <p>If you are fine with not knowing exactly which algorithm will be run (in particular, not knowing exactly whether a support array will be allocated),
|
|
+ * the dual-pivot parallel sorts in {@link java.util.Arrays}
|
|
+ * are about 50% faster than the classical single-pivot implementation used here.
|
|
+ *
|
|
+ * <p>In any case, if sorting time is important I suggest that you benchmark your sorting load
|
|
+ * with your data distribution and on your architecture.
|
|
+ *
|
|
+ * @see java.util.Arrays
|
|
+ */
|
|
+public class ObjectArrays {
|
|
+ private ObjectArrays() {}
|
|
+ /** A static, final, empty array. */
|
|
+ public final static Object[] EMPTY_ARRAY = {};
|
|
+ /** Creates a new array using a the given one as prototype.
|
|
+ *
|
|
+ * <P>This method returns a new array of the given length whose element
|
|
+ * are of the same class as of those of <code>prototype</code>. In case
|
|
+ * of an empty array, it tries to return {@link #EMPTY_ARRAY}, if possible.
|
|
+ *
|
|
+ * @param prototype an array that will be used to type the new one.
|
|
+ * @param length the length of the new array.
|
|
+ * @return a new array of given type and length.
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ private static <K> K[] newArray( final K[] prototype, final int length ) {
|
|
+ final Class<?> klass = prototype.getClass();
|
|
+ if ( klass == Object[].class ) return (K[])( length == 0 ? EMPTY_ARRAY : new Object[ length ] );
|
|
+ return (K[])java.lang.reflect.Array.newInstance( klass.getComponentType(), length );
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries.
|
|
+ *
|
|
+ * <P>If you cannot foresee whether this array will need again to be
|
|
+ * enlarged, you should probably use <code>grow()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it contains <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>array.length</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static <K> K[] ensureCapacity( final K[] array, final int length ) {
|
|
+ if ( length > array.length ) {
|
|
+ final K t[] =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, 0, t, 0, array.length );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Ensures that an array can contain the given number of entries, preserving just a part of the array.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @param preserve the number of elements of the array that must be preserved in case a new allocation is necessary.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code> entries or more; otherwise,
|
|
+ * an array with <code>length</code> entries whose first <code>preserve</code>
|
|
+ * entries are the same as those of <code>array</code>.
|
|
+ */
|
|
+ public static <K> K[] ensureCapacity( final K[] array, final int length, final int preserve ) {
|
|
+ if ( length > array.length ) {
|
|
+ final K t[] =
|
|
+ newArray( array, length );
|
|
+ System.arraycopy( array, 0, t, 0, preserve );
|
|
+ return t;
|
|
+ }
|
|
+ return array;
|
|
+ }
|
|
+ /** Grows the given array to the maximum between the given length and
|
|
+ * the current length multiplied by two, provided that the given
|
|
+ * length is larger than the current length.
|
|
+ *
|
|
+ * <P>If you want complete control on the array growth, you
|
|
+ * should probably use <code>ensureCapacity()</code> instead.
|
|
+ *
|
|
+ * @param array an array.
|
|
+ * @param length the new minimum length for this array.
|
|
+ * @return <code>array</code>, if it can contain <code>length</code>
|
|
+ * entries; otherwise, an array with
|
|
+ * max(<code>length</code>,<code>array.length</code>/φ) 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectBidirectionalIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import it.unimi.dsi.fastutil.BidirectionalIterator;
|
|
+/** A type-specific bidirectional iterator; provides an additional method to avoid (un)boxing,
|
|
+ * and the possibility to skip elements backwards.
|
|
+ *
|
|
+ * @see BidirectionalIterator
|
|
+ */
|
|
+public interface ObjectBidirectionalIterator <K> extends ObjectIterator <K>, BidirectionalIterator<K> {
|
|
+ /** Moves back for the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #previous()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasPrevious()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip back.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see java.util.Iterator#next()
|
|
+ */
|
|
+ int back( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollection.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link Collection}; provides some additional methods
|
|
+ * that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this class defines strengthens (again) {@link #iterator()} and defines
|
|
+ * a slightly different semantics for {@link #toArray(Object[])}.
|
|
+ *
|
|
+ * @see Collection
|
|
+ */
|
|
+public interface ObjectCollection <K> extends Collection<K>, ObjectIterable <K> {
|
|
+ /** Returns a type-specific iterator on the elements of this collection.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in
|
|
+ * {@link java.lang.Iterable#iterator()}, which was already
|
|
+ * strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Collection}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this collection.
|
|
+ */
|
|
+ ObjectIterator <K> iterator();
|
|
+ /** Returns a type-specific iterator on this elements of this collection.
|
|
+ *
|
|
+ * @see #iterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectIterator <K> objectIterator();
|
|
+ /** Returns an containing the items of this collection;
|
|
+ * the runtime type of the returned array is that of the specified array.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Note that, contrarily to {@link Collection#toArray(Object[])}, this
|
|
+ * methods just writes all elements of this collection: no special
|
|
+ * value will be added after the last one.
|
|
+ *
|
|
+ * @param a if this array is big enough, it will be used to store this collection.
|
|
+ * @return a primitive type array containing the items of this collection.
|
|
+ * @see Collection#toArray(Object[])
|
|
+ */
|
|
+ <T> T[] toArray(T[] a);
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectCollections.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
|
+/** A class providing static methods and objects that do useful things with type-specific collections.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectCollections {
|
|
+ private ObjectCollections() {}
|
|
+ /** An immutable class representing an empty type-specific collection.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific collection.
|
|
+ */
|
|
+ public abstract static class EmptyCollection <K> extends AbstractObjectCollection <K> {
|
|
+ protected EmptyCollection() {}
|
|
+ public boolean add( K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( Object k ) { return false; }
|
|
+ public Object[] toArray() { return ObjectArrays.EMPTY_ARRAY; }
|
|
+ public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ public <T> T[] toArray( T[] a ) { return a; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.EMPTY_ITERATOR; }
|
|
+ public int size() { return 0; }
|
|
+ public void clear() {}
|
|
+ public int hashCode() { return 0; }
|
|
+ public boolean equals( Object o ) {
|
|
+ if ( o == this ) return true;
|
|
+ if ( ! ( o instanceof Collection ) ) return false;
|
|
+ return ((Collection<?>)o).isEmpty();
|
|
+ }
|
|
+ }
|
|
+ /** A synchronized wrapper class for collections. */
|
|
+ public static class SynchronizedCollection <K> implements ObjectCollection <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectCollection <K> collection;
|
|
+ protected final Object sync;
|
|
+ protected SynchronizedCollection( final ObjectCollection <K> c, final Object sync ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = sync;
|
|
+ }
|
|
+ protected SynchronizedCollection( final ObjectCollection <K> c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ this.sync = this;
|
|
+ }
|
|
+ public int size() { synchronized( sync ) { return collection.size(); } }
|
|
+ public boolean isEmpty() { synchronized( sync ) { return collection.isEmpty(); } }
|
|
+ public boolean contains( final Object o ) { synchronized( sync ) { return collection.contains( o ); } }
|
|
+ public Object[] toArray() { synchronized( sync ) { return collection.toArray(); } }
|
|
+ public <T> T[] toArray( final T[] a ) { synchronized( sync ) { return collection.toArray( a ); } }
|
|
+ public ObjectIterator <K> iterator() { return collection.iterator(); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ public boolean add( final K k ) { synchronized( sync ) { return collection.add( k ); } }
|
|
+ public boolean rem( final Object k ) { synchronized( sync ) { return collection.remove( k ); } }
|
|
+ public boolean remove( final Object ok ) { synchronized( sync ) { return collection.remove( ok ); } }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { synchronized( sync ) { return collection.addAll( c ); } }
|
|
+ public boolean containsAll( final Collection<?> c ) { synchronized( sync ) { return collection.containsAll( c ); } }
|
|
+ public boolean removeAll( final Collection<?> c ) { synchronized( sync ) { return collection.removeAll( c ); } }
|
|
+ public boolean retainAll( final Collection<?> c ) { synchronized( sync ) { return collection.retainAll( c ); } }
|
|
+ public void clear() { synchronized( sync ) { collection.clear(); } }
|
|
+ public String toString() { synchronized( sync ) { return collection.toString(); } }
|
|
+ }
|
|
+ /** Returns a synchronized collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c ) { return new SynchronizedCollection <K>( c ); }
|
|
+ /** Returns a synchronized collection backed by the specified collection, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in a synchronized collection.
|
|
+ * @param sync an object that will be used to synchronize the list access.
|
|
+ * @return a synchronized view of the specified collection.
|
|
+ * @see java.util.Collections#synchronizedCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> synchronize( final ObjectCollection <K> c, final Object sync ) { return new SynchronizedCollection <K>( c, sync ); }
|
|
+ /** An unmodifiable wrapper class for collections. */
|
|
+ public static class UnmodifiableCollection <K> implements ObjectCollection <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectCollection <K> collection;
|
|
+ protected UnmodifiableCollection( final ObjectCollection <K> c ) {
|
|
+ if ( c == null ) throw new NullPointerException();
|
|
+ this.collection = c;
|
|
+ }
|
|
+ public int size() { return collection.size(); }
|
|
+ public boolean isEmpty() { return collection.isEmpty(); }
|
|
+ public boolean contains( final Object o ) { return collection.contains( o ); }
|
|
+ public ObjectIterator <K> iterator() { return ObjectIterators.unmodifiable( collection.iterator() ); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ public boolean add( final K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean remove( final Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean containsAll( final Collection<?> c ) { return collection.containsAll( c ); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public void clear() { throw new UnsupportedOperationException(); }
|
|
+ public String toString() { return collection.toString(); }
|
|
+ public <T> T[] toArray( final T[] a ) { return collection.toArray( a ); }
|
|
+ public Object[] toArray() { return collection.toArray(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified collection.
|
|
+ *
|
|
+ * @param c the collection to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable view of the specified collection.
|
|
+ * @see java.util.Collections#unmodifiableCollection(Collection)
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> unmodifiable( final ObjectCollection <K> c ) { return new UnmodifiableCollection <K>( c ); }
|
|
+ /** A collection wrapper class for iterables. */
|
|
+ public static class IterableCollection <K> extends AbstractObjectCollection <K> implements java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectIterable <K> iterable;
|
|
+ protected IterableCollection( final ObjectIterable <K> iterable ) {
|
|
+ if ( iterable == null ) throw new NullPointerException();
|
|
+ this.iterable = iterable;
|
|
+ }
|
|
+ public int size() {
|
|
+ int c = 0;
|
|
+ final ObjectIterator <K> iterator = iterator();
|
|
+ while( iterator.hasNext() ) {
|
|
+ iterator.next();
|
|
+ c++;
|
|
+ }
|
|
+ return c;
|
|
+ }
|
|
+ public boolean isEmpty() { return iterable.iterator().hasNext(); }
|
|
+ public ObjectIterator <K> iterator() { return iterable.iterator(); }
|
|
+ @Deprecated
|
|
+ public ObjectIterator <K> objectIterator() { return iterator(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable collection backed by the specified iterable.
|
|
+ *
|
|
+ * @param iterable the iterable object to be wrapped in an unmodifiable collection.
|
|
+ * @return an unmodifiable collection view of the specified iterable.
|
|
+ */
|
|
+ public static <K> ObjectCollection <K> asCollection( final ObjectIterable <K> iterable ) {
|
|
+ if ( iterable instanceof ObjectCollection ) return (ObjectCollection <K>)iterable;
|
|
+ return new IterableCollection <K>( iterable );
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterable.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.lang.Iterable;
|
|
+/** A type-specific {@link Iterable} that strengthens that specification of {@link Iterable#iterator()}.
|
|
+ *
|
|
+ * <p><strong>Warning</strong>: Java will let you write “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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Iterator;
|
|
+/** A type-specific {@link Iterator}; provides an additional method to avoid (un)boxing, and
|
|
+ * the possibility to skip elements.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public interface ObjectIterator <K> extends Iterator<K> {
|
|
+ /** Skips the given number of elements.
|
|
+ *
|
|
+ * <P>The effect of this call is exactly the same as that of
|
|
+ * calling {@link #next()} for <code>n</code> times (possibly stopping
|
|
+ * if {@link #hasNext()} becomes false).
|
|
+ *
|
|
+ * @param n the number of elements to skip.
|
|
+ * @return the number of elements actually skipped.
|
|
+ * @see Iterator#next()
|
|
+ */
|
|
+ int skip( int n );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectIterators.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Iterator;
|
|
+import java.util.ListIterator;
|
|
+import java.util.NoSuchElementException;
|
|
+/** A class providing static methods and objects that do useful things with type-specific iterators.
|
|
+ *
|
|
+ * @see Iterator
|
|
+ */
|
|
+public class ObjectIterators {
|
|
+ private ObjectIterators() {}
|
|
+ /** A class returning no elements and a type-specific iterator interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific iterator.
|
|
+ */
|
|
+ public static class EmptyIterator <K> extends AbstractObjectListIterator <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptyIterator() {}
|
|
+ public boolean hasNext() { return false; }
|
|
+ public boolean hasPrevious() { return false; }
|
|
+ public K next() { throw new NoSuchElementException(); }
|
|
+ public K previous() { throw new NoSuchElementException(); }
|
|
+ public int nextIndex() { return 0; }
|
|
+ public int previousIndex() { return -1; }
|
|
+ public int skip( int n ) { return 0; };
|
|
+ public int back( int n ) { return 0; };
|
|
+ public Object clone() { return EMPTY_ITERATOR; }
|
|
+ private Object readResolve() { return EMPTY_ITERATOR; }
|
|
+ }
|
|
+ /** An empty iterator (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>The class of this objects represent an abstract empty iterator
|
|
+ * that can iterate as a type-specific (list) iterator.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public final static EmptyIterator EMPTY_ITERATOR = new EmptyIterator();
|
|
+ /** An iterator returning a single element. */
|
|
+ private static class SingletonIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ private final K element;
|
|
+ private int curr;
|
|
+ public SingletonIterator( final K element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean hasNext() { return curr == 0; }
|
|
+ public boolean hasPrevious() { return curr == 1; }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ curr = 1;
|
|
+ return element;
|
|
+ }
|
|
+ public K previous() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ curr = 0;
|
|
+ return element;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Returns an iterator that iterates just over the given element.
|
|
+ *
|
|
+ * @param element the only element to be returned by a type-specific list iterator.
|
|
+ * @return an iterator that iterates just over <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> singleton( final K element ) {
|
|
+ return new SingletonIterator <K>( element );
|
|
+ }
|
|
+ /** A class to wrap arrays in iterators. */
|
|
+ private static class ArrayIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ private final K[] array;
|
|
+ private final int offset, length;
|
|
+ private int curr;
|
|
+ public ArrayIterator( final K[] array, final int offset, final int length ) {
|
|
+ this.array = array;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ }
|
|
+ public boolean hasNext() { return curr < length; }
|
|
+ public boolean hasPrevious() { return curr > 0; }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ return array[ offset + curr++ ];
|
|
+ }
|
|
+ public K previous() {
|
|
+ if ( ! hasPrevious() ) throw new NoSuchElementException();
|
|
+ return array[ offset + --curr ];
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ if ( n <= length - curr ) {
|
|
+ curr += n;
|
|
+ return n;
|
|
+ }
|
|
+ n = length - curr;
|
|
+ curr = length;
|
|
+ return n;
|
|
+ }
|
|
+ public int back( int n ) {
|
|
+ if ( n <= curr ) {
|
|
+ curr -= n;
|
|
+ return n;
|
|
+ }
|
|
+ n = curr;
|
|
+ curr = 0;
|
|
+ return n;
|
|
+ }
|
|
+ public int nextIndex() {
|
|
+ return curr;
|
|
+ }
|
|
+ public int previousIndex() {
|
|
+ return curr - 1;
|
|
+ }
|
|
+ }
|
|
+ /** Wraps the given part of an array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will iterate
|
|
+ * <code>length</code> times, returning consecutive elements of the given
|
|
+ * array starting from the one with index <code>offset</code>.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param length the number of elements to return.
|
|
+ * @return an iterator that will return <code>length</code> elements of <code>array</code> starting at position <code>offset</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> wrap( final K[] array, final int offset, final int length ) {
|
|
+ ObjectArrays.ensureOffsetLength( array, offset, length );
|
|
+ return new ArrayIterator <K>( array, offset, length );
|
|
+ }
|
|
+ /** Wraps the given array into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>The type-specific list iterator returned by this method will return
|
|
+ * all elements of the given array.
|
|
+ *
|
|
+ * @param array an array to wrap into a type-specific list iterator.
|
|
+ * @return an iterator that will the elements of <code>array</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> wrap( final K[] array ) {
|
|
+ return new ArrayIterator <K>( array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator into an array starting at a given offset for a given number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>length</code>, in the given array starting at <code>offset</code>.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @param offset the first element of the array to be returned.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[], int offset, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ if ( offset < 0 || offset + max > array.length ) throw new IllegalArgumentException();
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) array[ offset++ ] = i.next();
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given array. The iteration will stop when the
|
|
+ * iterator has no more elements or when the end of the array has been reached.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param array an array to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped.
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <? extends K> i, final K array[] ) {
|
|
+ return unwrap( i, array, 0, array.length );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator. At most <code>max</code> elements
|
|
+ * will be returned.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be unwrapped.
|
|
+ * @return an array containing the elements returned by the iterator (at most <code>max</code>).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> K[] unwrap( final Iterator <? extends K> i, int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ K array[] = (K[]) new Object[ 16 ];
|
|
+ int j = 0;
|
|
+ while( max-- != 0 && i.hasNext() ) {
|
|
+ if ( j == array.length ) array = ObjectArrays.grow( array, j + 1 );
|
|
+ array[ j++ ] = i.next();
|
|
+ }
|
|
+ return ObjectArrays.trim( array, j );
|
|
+ }
|
|
+ /** Unwraps an iterator, returning an array.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns an array
|
|
+ * containing the elements returned by the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return an array containing the elements returned by the iterator.
|
|
+ */
|
|
+ public static <K> K[] unwrap( final Iterator <? extends K> i ) {
|
|
+ return unwrap( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the elements
|
|
+ * returned, up to a maximum of <code>max</code>, in the given type-specific collection.
|
|
+ * The number of actually unwrapped elements is returned (it may be less than <code>max</code> if
|
|
+ * the iterator emits less than <code>max</code> elements).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection array to contain the output of the iterator.
|
|
+ * @param max the maximum number of elements to unwrap.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int unwrap( final Iterator <K> i, final ObjectCollection <? super K> c, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) c.add( i.next() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Unwraps an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and stores the
|
|
+ * elements returned in the given type-specific collection. The returned count on the number
|
|
+ * unwrapped elements is a long, so that it will work also with very large collections.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param c a type-specific collection to contain the output of the iterator.
|
|
+ * @return the number of elements unwrapped. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> long unwrap( final Iterator <K> i, final ObjectCollection <? super K> c ) {
|
|
+ long n = 0;
|
|
+ while( i.hasNext() ) {
|
|
+ c.add( i.next() );
|
|
+ n++;
|
|
+ }
|
|
+ return n;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection (up to <code>max</code>).
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s, final int max ) {
|
|
+ if ( max < 0 ) throw new IllegalArgumentException( "The maximum number of elements (" + max + ") is negative" );
|
|
+ int j = max;
|
|
+ while( j-- != 0 && i.hasNext() ) s.add( i.next() );
|
|
+ return max - j - 1;
|
|
+ }
|
|
+ /** Pours an iterator into a type-specific collection.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and adds
|
|
+ * the returned elements to the given collection.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param s a type-specific collection.
|
|
+ * @return the number of elements poured. Note that
|
|
+ * this is the number of elements returned by the iterator, which is not necessarily the number
|
|
+ * of elements that have been added to the collection (because of duplicates).
|
|
+ */
|
|
+ public static <K> int pour( final Iterator <K> i, final ObjectCollection <? super K> s ) {
|
|
+ return pour( i, s, Integer.MAX_VALUE );
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list, with a limit on the number of elements.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a type-specific list containing the returned elements (up to <code>max</code>). Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @param max the maximum number of elements to be poured.
|
|
+ * @return a type-specific list containing the returned elements, up to <code>max</code>.
|
|
+ */
|
|
+ public static <K> ObjectList <K> pour( final Iterator <K> i, int max ) {
|
|
+ final ObjectArrayList <K> l = new ObjectArrayList <K>();
|
|
+ pour( i, l, max );
|
|
+ l.trim();
|
|
+ return l;
|
|
+ }
|
|
+ /** Pours an iterator, returning a type-specific list.
|
|
+ *
|
|
+ * <P>This method iterates over the given type-specific iterator and returns
|
|
+ * a list containing the returned elements. Iteration
|
|
+ * on the returned list is guaranteed to produce the elements in the same order
|
|
+ * in which they appeared in the iterator.
|
|
+ *
|
|
+ * @param i a type-specific iterator.
|
|
+ * @return a type-specific list containing the returned elements.
|
|
+ */
|
|
+ public static <K> ObjectList <K> pour( final Iterator <K> i ) {
|
|
+ return pour( i, Integer.MAX_VALUE );
|
|
+ }
|
|
+ private static class IteratorWrapper <K> extends AbstractObjectIterator <K> {
|
|
+ final Iterator<K> i;
|
|
+ public IteratorWrapper( final Iterator<K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public K next() { return (i.next()); }
|
|
+ }
|
|
+ /** Wraps a standard iterator into a type-specific iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard iterator into a type-specific one which will handle the
|
|
+ * type conversions for you. Of course, any attempt to wrap an iterator returning the
|
|
+ * instances of the wrong class will generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i an iterator.
|
|
+ * @return a type-specific iterator backed by <code>i</code>.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> asObjectIterator( final Iterator <K> i ) {
|
|
+ if ( i instanceof ObjectIterator ) return (ObjectIterator <K>)i;
|
|
+ return new IteratorWrapper <K>( i );
|
|
+ }
|
|
+ private static class ListIteratorWrapper <K> extends AbstractObjectListIterator <K> {
|
|
+ final ListIterator<K> i;
|
|
+ public ListIteratorWrapper( final ListIterator<K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ public void set( K k ) { i.set( (k) ); }
|
|
+ public void add( K k ) { i.add( (k) ); }
|
|
+ public void remove() { i.remove(); }
|
|
+ public K next() { return (i.next()); }
|
|
+ public K previous() { return (i.previous()); }
|
|
+ }
|
|
+ /** Wraps a standard list iterator into a type-specific list iterator.
|
|
+ *
|
|
+ * <P>This method wraps a standard list iterator into a type-specific one
|
|
+ * which will handle the type conversions for you. Of course, any attempt
|
|
+ * to wrap an iterator returning the instances of the wrong class will
|
|
+ * generate a {@link ClassCastException}. The
|
|
+ * returned iterator is backed by <code>i</code>: changes to one of the iterators
|
|
+ * will affect the other, too.
|
|
+ *
|
|
+ * <P>If <code>i</code> is already type-specific, it will returned and no new object
|
|
+ * will be generated.
|
|
+ *
|
|
+ * @param i a list iterator.
|
|
+ * @return a type-specific list iterator backed by <code>i</code>.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> asObjectIterator( final ListIterator <K> i ) {
|
|
+ if ( i instanceof ObjectListIterator ) return (ObjectListIterator <K>)i;
|
|
+ return new ListIteratorWrapper <K>( i );
|
|
+ }
|
|
+ private static class IteratorConcatenator <K> extends AbstractObjectIterator <K> {
|
|
+ final ObjectIterator <? extends K> a[];
|
|
+ int offset, length, lastOffset = -1;
|
|
+ public IteratorConcatenator( final ObjectIterator <? extends K> a[], int offset, int length ) {
|
|
+ this.a = a;
|
|
+ this.offset = offset;
|
|
+ this.length = length;
|
|
+ advance();
|
|
+ }
|
|
+ private void advance() {
|
|
+ while( length != 0 ) {
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return;
|
|
+ }
|
|
+ public boolean hasNext() {
|
|
+ return length > 0;
|
|
+ }
|
|
+ public K next() {
|
|
+ if ( ! hasNext() ) throw new NoSuchElementException();
|
|
+ K next = a[ lastOffset = offset ].next();
|
|
+ advance();
|
|
+ return next;
|
|
+ }
|
|
+ public void remove() {
|
|
+ if ( lastOffset == -1 ) throw new IllegalStateException();
|
|
+ a[ lastOffset ].remove();
|
|
+ }
|
|
+ public int skip( int n ) {
|
|
+ lastOffset = -1;
|
|
+ int skipped = 0;
|
|
+ while( skipped < n && length != 0 ) {
|
|
+ skipped += a[ offset ].skip( n - skipped );
|
|
+ if ( a[ offset ].hasNext() ) break;
|
|
+ length--;
|
|
+ offset++;
|
|
+ }
|
|
+ return skipped;
|
|
+ }
|
|
+ }
|
|
+ /** Concatenates all iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by all iterators contained in the given array.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @return an iterator obtained by concatenation.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[] ) {
|
|
+ return concat( a, 0, a.length );
|
|
+ }
|
|
+ /** Concatenates a sequence of iterators contained in an array.
|
|
+ *
|
|
+ * <P>This method returns an iterator that will enumerate in order the elements returned
|
|
+ * by <code>a[ offset ]</code>, then those returned
|
|
+ * by <code>a[ offset + 1 ]</code>, and so on up to
|
|
+ * <code>a[ offset + length - 1 ]</code>.
|
|
+ *
|
|
+ * @param a an array of iterators.
|
|
+ * @param offset the index of the first iterator to concatenate.
|
|
+ * @param length the number of iterators to concatenate.
|
|
+ * @return an iterator obtained by concatenation of <code>length</code> elements of <code>a</code> starting at <code>offset</code>.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> concat( final ObjectIterator <? extends K> a[], final int offset, final int length ) {
|
|
+ return new IteratorConcatenator <K>( a, offset, length );
|
|
+ }
|
|
+ /** An unmodifiable wrapper class for iterators. */
|
|
+ public static class UnmodifiableIterator <K> extends AbstractObjectIterator <K> {
|
|
+ final protected ObjectIterator <K> i;
|
|
+ public UnmodifiableIterator( final ObjectIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public K next() { return i.next(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable iterator backed by the specified iterator.
|
|
+ *
|
|
+ * @param i the iterator to be wrapped in an unmodifiable iterator.
|
|
+ * @return an unmodifiable view of the specified iterator.
|
|
+ */
|
|
+ public static <K> ObjectIterator <K> unmodifiable( final ObjectIterator <K> i ) { return new UnmodifiableIterator <K>( i ); }
|
|
+ /** An unmodifiable wrapper class for bidirectional iterators. */
|
|
+ public static class UnmodifiableBidirectionalIterator <K> extends AbstractObjectBidirectionalIterator <K> {
|
|
+ final protected ObjectBidirectionalIterator <K> i;
|
|
+ public UnmodifiableBidirectionalIterator( final ObjectBidirectionalIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public K next() { return i.next(); }
|
|
+ public K previous() { return i.previous(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable bidirectional iterator backed by the specified bidirectional iterator.
|
|
+ *
|
|
+ * @param i the bidirectional iterator to be wrapped in an unmodifiable bidirectional iterator.
|
|
+ * @return an unmodifiable view of the specified bidirectional iterator.
|
|
+ */
|
|
+ public static <K> ObjectBidirectionalIterator <K> unmodifiable( final ObjectBidirectionalIterator <K> i ) { return new UnmodifiableBidirectionalIterator <K>( i ); }
|
|
+ /** An unmodifiable wrapper class for list iterators. */
|
|
+ public static class UnmodifiableListIterator <K> extends AbstractObjectListIterator <K> {
|
|
+ final protected ObjectListIterator <K> i;
|
|
+ public UnmodifiableListIterator( final ObjectListIterator <K> i ) {
|
|
+ this.i = i;
|
|
+ }
|
|
+ public boolean hasNext() { return i.hasNext(); }
|
|
+ public boolean hasPrevious() { return i.hasPrevious(); }
|
|
+ public K next() { return i.next(); }
|
|
+ public K previous() { return i.previous(); }
|
|
+ public int nextIndex() { return i.nextIndex(); }
|
|
+ public int previousIndex() { return i.previousIndex(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable list iterator backed by the specified list iterator.
|
|
+ *
|
|
+ * @param i the list iterator to be wrapped in an unmodifiable list iterator.
|
|
+ * @return an unmodifiable view of the specified list iterator.
|
|
+ */
|
|
+ public static <K> ObjectListIterator <K> unmodifiable( final ObjectListIterator <K> i ) { return new UnmodifiableListIterator <K>( i ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectList.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.List;
|
|
+/** A type-specific {@link List}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Note that this type-specific interface extends {@link Comparable}: it is expected that implementing
|
|
+ * classes perform a lexicographical comparison using the standard operator "less then" for primitive types,
|
|
+ * and the usual {@link Comparable#compareTo(Object) compareTo()} method for objects.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #listIterator()},
|
|
+ * {@link #listIterator(int)} and {@link #subList(int,int)}.
|
|
+ *
|
|
+ * <P>Besides polymorphic methods, this interfaces specifies methods to copy into an array or remove contiguous
|
|
+ * sublists. Although the abstract implementation of this interface provides simple, one-by-one implementations
|
|
+ * of these methods, it is expected that concrete implementation override them with optimized versions.
|
|
+ *
|
|
+ * @see List
|
|
+ */
|
|
+public interface ObjectList <K> extends List<K>, Comparable<List<? extends K>>, ObjectCollection <K> {
|
|
+ /** Returns a type-specific iterator on the elements of this list (in proper sequence).
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in {@link List#iterator()}.
|
|
+ * It would not be normally necessary, but {@link java.lang.Iterable#iterator()} is bizarrily re-specified
|
|
+ * in {@link List}.
|
|
+ *
|
|
+ * @return an iterator on the elements of this list (in proper sequence).
|
|
+ */
|
|
+ ObjectListIterator <K> iterator();
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see #listIterator()
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectListIterator <K> objectListIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see #listIterator(int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #listIterator(int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectListIterator <K> objectListIterator( int index );
|
|
+ /** Returns a type-specific list iterator on the list.
|
|
+ *
|
|
+ * @see List#listIterator()
|
|
+ */
|
|
+ ObjectListIterator <K> listIterator();
|
|
+ /** Returns a type-specific list iterator on the list starting at a given index.
|
|
+ *
|
|
+ * @see List#listIterator(int)
|
|
+ */
|
|
+ ObjectListIterator <K> listIterator( int index );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ * @see List#subList(int,int)
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #subList(int,int)}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectList <K> objectSubList( int from, int to );
|
|
+ /** Returns a type-specific view of the portion of this list from the index <code>from</code>, inclusive, to the index <code>to</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link List#subList(int,int)}.
|
|
+ *
|
|
+ * @see List#subList(int,int)
|
|
+ */
|
|
+ ObjectList <K> subList(int from, int to);
|
|
+ /** Sets the size of this list.
|
|
+ *
|
|
+ * <P>If the specified size is smaller than the current size, the last elements are
|
|
+ * discarded. Otherwise, they are filled with 0/<code>null</code>/<code>false</code>.
|
|
+ *
|
|
+ * @param size the new size.
|
|
+ */
|
|
+ void size( int size );
|
|
+ /** Copies (hopefully quickly) elements of this type-specific list into the given array.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param a the destination array.
|
|
+ * @param offset the offset into the destination array where to store the first element copied.
|
|
+ * @param length the number of elements to be copied.
|
|
+ */
|
|
+ void getElements( int from, Object a[], int offset, int length );
|
|
+ /** Removes (hopefully quickly) elements of this type-specific list.
|
|
+ *
|
|
+ * @param from the start index (inclusive).
|
|
+ * @param to the end index (exclusive).
|
|
+ */
|
|
+ void removeElements( int from, int to );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ */
|
|
+ void addElements( int index, K a[] );
|
|
+ /** Add (hopefully quickly) elements to this type-specific list.
|
|
+ *
|
|
+ * @param index the index at which to add elements.
|
|
+ * @param a the array containing the elements.
|
|
+ * @param offset the offset of the first element to add.
|
|
+ * @param length the number of elements to add.
|
|
+ */
|
|
+ void addElements( int index, K a[], int offset, int length );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectListIterator.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.ListIterator;
|
|
+/** A type-specific bidirectional iterator that is also a {@link ListIterator}.
|
|
+ *
|
|
+ * <P>This interface merges the methods provided by a {@link ListIterator} and
|
|
+ * a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator}. Moreover, it provides
|
|
+ * type-specific versions of {@link java.util.ListIterator#add(Object) add()}
|
|
+ * and {@link java.util.ListIterator#set(Object) set()}.
|
|
+ *
|
|
+ * @see java.util.ListIterator
|
|
+ * @see it.unimi.dsi.fastutil.BidirectionalIterator
|
|
+ */
|
|
+public interface ObjectListIterator <K> extends ListIterator<K>, ObjectBidirectionalIterator <K> {
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Set;
|
|
+/** A type-specific {@link Set}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens (again) {@link #iterator()}.
|
|
+ *
|
|
+ * @see Set
|
|
+ */
|
|
+public interface ObjectSet <K> extends ObjectCollection <K>, Set<K> {
|
|
+ /** Returns a type-specific iterator on the elements of this set.
|
|
+ *
|
|
+ * <p>Note that this specification strengthens the one given in {@link java.lang.Iterable#iterator()},
|
|
+ * which was already strengthened in the corresponding type-specific class,
|
|
+ * but was weakened by the fact that this interface extends {@link Set}.
|
|
+ *
|
|
+ * @return a type-specific iterator on the elements of this set.
|
|
+ */
|
|
+ ObjectIterator <K> iterator();
|
|
+ /** Removes an element from this set.
|
|
+ *
|
|
+ * <p>Note that the corresponding method of the type-specific collection is <code>rem()</code>.
|
|
+ * This unfortunate situation is caused by the clash
|
|
+ * with the similarly named index-based method in the {@link java.util.List} interface.
|
|
+ *
|
|
+ * @see java.util.Collection#remove(Object)
|
|
+ */
|
|
+ public boolean remove( Object k );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.Collection;
|
|
+import java.util.Set;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectSets {
|
|
+ private ObjectSets() {}
|
|
+ /** An immutable class representing the empty set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set.
|
|
+ */
|
|
+ public static class EmptySet <K> extends ObjectCollections.EmptyCollection <K> implements ObjectSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public boolean equals( final Object o ) { return o instanceof Set && ((Set)o).isEmpty(); }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty set (immutable). It is serializable and cloneable.
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** Return an empty set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
|
|
+ * @return an empty set (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> ObjectSet <K> emptySet() {
|
|
+ return EMPTY_SET;
|
|
+ }
|
|
+ /** An immutable class representing a type-specific singleton set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific set. */
|
|
+ public static class Singleton <K> extends AbstractObjectSet <K> implements java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final K element;
|
|
+ protected Singleton( final K element ) {
|
|
+ this.element = element;
|
|
+ }
|
|
+ public boolean add( final K k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean contains( final Object k ) { return ( (k) == null ? (element) == null : (k).equals(element) ); }
|
|
+ public boolean addAll( final Collection<? extends K> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean removeAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean retainAll( final Collection<?> c ) { throw new UnsupportedOperationException(); }
|
|
+ public ObjectListIterator <K> iterator() { return ObjectIterators.singleton( element ); }
|
|
+ public int size() { return 1; }
|
|
+ public Object clone() { return this; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable set containing only the specified element. The returned set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned set.
|
|
+ * @return a type-specific immutable set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSet <K> singleton( final K element ) {
|
|
+ return new Singleton <K>( element );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sets. */
|
|
+ public static class SynchronizedSet <K> extends ObjectCollections.SynchronizedCollection <K> implements ObjectSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected SynchronizedSet( final ObjectSet <K> s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ }
|
|
+ protected SynchronizedSet( final ObjectSet <K> s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final Object k ) { synchronized( sync ) { return collection.remove( (k) ); } }
|
|
+ public boolean equals( final Object o ) { synchronized( sync ) { return collection.equals( o ); } }
|
|
+ public int hashCode() { synchronized( sync ) { return collection.hashCode(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s ) { return new SynchronizedSet <K>( s ); }
|
|
+ /** Returns a synchronized type-specific set backed by the given type-specific set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the set to be wrapped in a synchronized set.
|
|
+ * @param sync an object that will be used to synchronize the access to the set.
|
|
+ * @return a synchronized view of the specified set.
|
|
+ * @see java.util.Collections#synchronizedSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> synchronize( final ObjectSet <K> s, final Object sync ) { return new SynchronizedSet <K>( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sets. */
|
|
+ public static class UnmodifiableSet <K> extends ObjectCollections.UnmodifiableCollection <K> implements ObjectSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected UnmodifiableSet( final ObjectSet <K> s ) {
|
|
+ super( s );
|
|
+ }
|
|
+ public boolean remove( final Object k ) { throw new UnsupportedOperationException(); }
|
|
+ public boolean equals( final Object o ) { return collection.equals( o ); }
|
|
+ public int hashCode() { return collection.hashCode(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific set backed by the given type-specific set.
|
|
+ *
|
|
+ * @param s the set to be wrapped in an unmodifiable set.
|
|
+ * @return an unmodifiable view of the specified set.
|
|
+ * @see java.util.Collections#unmodifiableSet(Set)
|
|
+ */
|
|
+ public static <K> ObjectSet <K> unmodifiable( final ObjectSet <K> s ) { return new UnmodifiableSet <K>( s ); }
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSet.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.SortedSet;
|
|
+import java.util.Collection;
|
|
+/** A type-specific {@link SortedSet}; provides some additional methods that use polymorphism to avoid (un)boxing.
|
|
+ *
|
|
+ * <P>Additionally, this interface strengthens {@link #iterator()},
|
|
+ * {@link #comparator()} (for primitive types), {@link SortedSet#subSet(Object,Object)},
|
|
+ * {@link SortedSet#headSet(Object)} and {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet
|
|
+ */
|
|
+public interface ObjectSortedSet <K> extends ObjectSet <K>, SortedSet<K> {
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set, starting from a given element of the domain (optional operation).
|
|
+ *
|
|
+ * <P>This method returns a type-specific bidirectional iterator with given
|
|
+ * starting point. The starting point is any element comparable to the
|
|
+ * elements of this set (even if it does not actually belong to the
|
|
+ * set). The next element of the returned iterator is the least element of
|
|
+ * the set that is greater than the starting point (if there are no
|
|
+ * elements greater than the starting point, {@link
|
|
+ * it.unimi.dsi.fastutil.BidirectionalIterator#hasNext() hasNext()} will return
|
|
+ * <code>false</code>). The previous element of the returned iterator is
|
|
+ * the greatest element of the set that is smaller than or equal to the
|
|
+ * starting point (if there are no elements smaller than or equal to the
|
|
+ * starting point, {@link it.unimi.dsi.fastutil.BidirectionalIterator#hasPrevious()
|
|
+ * hasPrevious()} will return <code>false</code>).
|
|
+ *
|
|
+ * <P>Note that passing the last element of the set as starting point and
|
|
+ * calling {@link it.unimi.dsi.fastutil.BidirectionalIterator#previous() previous()} you can traverse the
|
|
+ * entire set in reverse order.
|
|
+ *
|
|
+ * @param fromElement an element to start from.
|
|
+ * @return a bidirectional iterator on the element in this set, starting at the given element.
|
|
+ * @throws UnsupportedOperationException if this set does not support iterators with a starting point.
|
|
+ */
|
|
+ ObjectBidirectionalIterator <K> iterator( K fromElement );
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} iterator on the collection.
|
|
+ *
|
|
+ * <P>The iterator returned by the {@link #iterator()} method and by this
|
|
+ * method are identical; however, using this method you can save a type casting.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @deprecated As of <code>fastutil</code> 5, replaced by {@link #iterator()}.
|
|
+ */
|
|
+ @Deprecated
|
|
+ ObjectBidirectionalIterator <K> objectIterator();
|
|
+ /** Returns a type-specific {@link it.unimi.dsi.fastutil.BidirectionalIterator} on the elements in
|
|
+ * this set.
|
|
+ *
|
|
+ * <P>This method returns a parameterised bidirectional iterator. The iterator
|
|
+ * can be moreover safely cast to a type-specific iterator.
|
|
+ *
|
|
+ * Note that this specification strengthens the one given in the corresponding type-specific
|
|
+ * {@link Collection}.
|
|
+ *
|
|
+ * @return a bidirectional iterator on the element in this set.
|
|
+ */
|
|
+ ObjectBidirectionalIterator <K> iterator();
|
|
+ /** Returns a view of the portion of this sorted set whose elements range from <code>fromElement</code>, inclusive, to <code>toElement</code>, exclusive.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#subSet(Object,Object)}.
|
|
+ *
|
|
+ * @see SortedSet#subSet(Object,Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> subSet( K fromElement, K toElement) ;
|
|
+ /** Returns a view of the portion of this sorted set whose elements are strictly less than <code>toElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#headSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#headSet(Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> headSet( K toElement );
|
|
+ /** Returns a view of the portion of this sorted set whose elements are greater than or equal to <code>fromElement</code>.
|
|
+ *
|
|
+ * <P>Note that this specification strengthens the one given in {@link SortedSet#tailSet(Object)}.
|
|
+ *
|
|
+ * @see SortedSet#tailSet(Object)
|
|
+ */
|
|
+ ObjectSortedSet <K> tailSet( K fromElement );
|
|
+}
|
|
diff --git a/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
|
|
--- /dev/null
|
|
+++ b/src/main/java/it/unimi/dsi/fastutil/objects/ObjectSortedSets.java
|
|
@@ -0,0 +0,0 @@
|
|
+/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+/* This header is separate from features.h so that the compiler can
|
|
+ include it implicitly at the start of every compilation. It must
|
|
+ not itself include <features.h> or any other header that includes
|
|
+ <features.h> because the implicit include comes before any feature
|
|
+ test macros that may be defined in a source file before it first
|
|
+ explicitly includes a system header. GCC knows the name of this
|
|
+ header in order to preinclude it. */
|
|
+/* glibc's intent is to support the IEC 559 math functionality, real
|
|
+ and complex. If the GCC (4.9 and later) predefined macros
|
|
+ specifying compiler intent are available, use them to determine
|
|
+ whether the overall intent is to support these features; otherwise,
|
|
+ presume an older compiler has intent to support these features and
|
|
+ define these macros by default. */
|
|
+/* wchar_t uses ISO/IEC 10646 (2nd ed., published 2011-03-15) /
|
|
+ Unicode 6.0. */
|
|
+/* We do not support C11 <threads.h>. */
|
|
+/* Generic definitions */
|
|
+/* Assertions (useful to generate conditional code) */
|
|
+/* Current type and class (and size, if applicable) */
|
|
+/* Value methods */
|
|
+/* Interfaces (keys) */
|
|
+/* Interfaces (values) */
|
|
+/* Abstract implementations (keys) */
|
|
+/* Abstract implementations (values) */
|
|
+/* Static containers (keys) */
|
|
+/* Static containers (values) */
|
|
+/* Implementations */
|
|
+/* Synchronized wrappers */
|
|
+/* Unmodifiable wrappers */
|
|
+/* Other wrappers */
|
|
+/* Methods (keys) */
|
|
+/* Methods (values) */
|
|
+/* Methods (keys/values) */
|
|
+/* Methods that have special names depending on keys (but the special names depend on values) */
|
|
+/* Equality */
|
|
+/* Object/Reference-only definitions (keys) */
|
|
+/* Object/Reference-only definitions (values) */
|
|
+/*
|
|
+ * Copyright (C) 2002-2016 Sebastiano Vigna
|
|
+ *
|
|
+ * Licensed under the Apache License, Version 2.0 (the "License");
|
|
+ * you may not use this file except in compliance with the License.
|
|
+ * You may obtain a copy of the License at
|
|
+ *
|
|
+ * http://www.apache.org/licenses/LICENSE-2.0
|
|
+ *
|
|
+ * Unless required by applicable law or agreed to in writing, software
|
|
+ * distributed under the License is distributed on an "AS IS" BASIS,
|
|
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
+ * See the License for the specific language governing permissions and
|
|
+ * limitations under the License.
|
|
+ */
|
|
+package it.unimi.dsi.fastutil.objects;
|
|
+import java.util.SortedSet;
|
|
+import java.util.NoSuchElementException;
|
|
+import java.util.Comparator;
|
|
+/** A class providing static methods and objects that do useful things with type-specific sorted sets.
|
|
+ *
|
|
+ * @see java.util.Collections
|
|
+ */
|
|
+public class ObjectSortedSets {
|
|
+ private ObjectSortedSets() {}
|
|
+ /** An immutable class representing the empty sorted set and implementing a type-specific set interface.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class EmptySet <K> extends ObjectSets.EmptySet <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected EmptySet() {}
|
|
+ public boolean remove( Object ok ) { throw new UnsupportedOperationException(); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectBidirectionalIterator <K> iterator( K from ) { return ObjectIterators.EMPTY_ITERATOR; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> subSet( K from, K to ) { return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> headSet( K from ) { return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> tailSet( K to ) { return EMPTY_SET; }
|
|
+ public K first() { throw new NoSuchElementException(); }
|
|
+ public K last() { throw new NoSuchElementException(); }
|
|
+ public Comparator <? super K> comparator() { return null; }
|
|
+ public Object clone() { return EMPTY_SET; }
|
|
+ private Object readResolve() { return EMPTY_SET; }
|
|
+ }
|
|
+ /** An empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ */
|
|
+ @SuppressWarnings("rawtypes")
|
|
+ public static final EmptySet EMPTY_SET = new EmptySet();
|
|
+ /** Return an empty sorted set (immutable). It is serializable and cloneable.
|
|
+ *
|
|
+ * <P>This method provides a typesafe access to {@link #EMPTY_SET}.
|
|
+ * @return an empty sorted set (immutable).
|
|
+ */
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public static <K> ObjectSet <K> emptySet() {
|
|
+ return EMPTY_SET;
|
|
+ }
|
|
+ /** A class representing a singleton sorted set.
|
|
+ *
|
|
+ * <P>This class may be useful to implement your own in case you subclass
|
|
+ * a type-specific sorted set.
|
|
+ */
|
|
+ public static class Singleton <K> extends ObjectSets.Singleton <K> implements ObjectSortedSet <K>, java.io.Serializable, Cloneable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ final Comparator <? super K> comparator;
|
|
+ private Singleton( final K element, final Comparator <? super K> comparator ) {
|
|
+ super( element );
|
|
+ this.comparator = comparator;
|
|
+ }
|
|
+ private Singleton( final K element ) {
|
|
+ this( element, null );
|
|
+ }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ final int compare( final K k1, final K k2 ) {
|
|
+ return comparator == null ? ( ((Comparable<K>)(k1)).compareTo(k2) ) : comparator.compare( k1, k2 );
|
|
+ }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() {
|
|
+ return iterator();
|
|
+ }
|
|
+ public ObjectBidirectionalIterator <K> iterator( K from ) {
|
|
+ ObjectBidirectionalIterator <K> i = iterator();
|
|
+ if ( compare( element, from ) <= 0 ) i.next();
|
|
+ return i;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { return comparator; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { if ( compare( from, element ) <= 0 && compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { if ( compare( element, to ) < 0 ) return this; return EMPTY_SET; }
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { if ( compare( from, element ) <= 0 ) return this; return EMPTY_SET; }
|
|
+ public K first() { return element; }
|
|
+ public K last() { return element; }
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> singleton( final K element ) {
|
|
+ return new Singleton <K>( element );
|
|
+ }
|
|
+ /** Returns a type-specific immutable sorted set containing only the specified element, and using a specified comparator. The returned sorted set is serializable and cloneable.
|
|
+ *
|
|
+ * @param element the only element of the returned sorted set.
|
|
+ * @param comparator the comparator to use in the returned sorted set.
|
|
+ * @return a type-specific immutable sorted set containing just <code>element</code>.
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> singleton( final K element, final Comparator <? super K> comparator ) {
|
|
+ return new Singleton <K>( element, comparator );
|
|
+ }
|
|
+ /** A synchronized wrapper class for sorted sets. */
|
|
+ public static class SynchronizedSortedSet <K> extends ObjectSets.SynchronizedSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectSortedSet <K> sortedSet;
|
|
+ protected SynchronizedSortedSet( final ObjectSortedSet <K> s, final Object sync ) {
|
|
+ super( s, sync );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ protected SynchronizedSortedSet( final ObjectSortedSet <K> s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { synchronized( sync ) { return sortedSet.comparator(); } }
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { return new SynchronizedSortedSet <K>( sortedSet.subSet( from, to ), sync ); }
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { return new SynchronizedSortedSet <K>( sortedSet.headSet( to ), sync ); }
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { return new SynchronizedSortedSet <K>( sortedSet.tailSet( from ), sync ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return sortedSet.iterator(); }
|
|
+ public ObjectBidirectionalIterator <K> iterator( final K from ) { return sortedSet.iterator( from ); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return sortedSet.iterator(); }
|
|
+ public K first() { synchronized( sync ) { return sortedSet.first(); } }
|
|
+ public K last() { synchronized( sync ) { return sortedSet.last(); } }
|
|
+ }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s ) { return new SynchronizedSortedSet <K>( s ); }
|
|
+ /** Returns a synchronized type-specific sorted set backed by the given type-specific sorted set, using an assigned object to synchronize.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in a synchronized sorted set.
|
|
+ * @param sync an object that will be used to synchronize the access to the sorted set.
|
|
+ * @return a synchronized view of the specified sorted set.
|
|
+ * @see java.util.Collections#synchronizedSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> synchronize( final ObjectSortedSet <K> s, final Object sync ) { return new SynchronizedSortedSet <K>( s, sync ); }
|
|
+ /** An unmodifiable wrapper class for sorted sets. */
|
|
+ public static class UnmodifiableSortedSet <K> extends ObjectSets.UnmodifiableSet <K> implements ObjectSortedSet <K>, java.io.Serializable {
|
|
+ private static final long serialVersionUID = -7046029254386353129L;
|
|
+ protected final ObjectSortedSet <K> sortedSet;
|
|
+ protected UnmodifiableSortedSet( final ObjectSortedSet <K> s ) {
|
|
+ super( s );
|
|
+ sortedSet = s;
|
|
+ }
|
|
+ public Comparator <? super K> comparator() { return sortedSet.comparator(); }
|
|
+ public ObjectSortedSet <K> subSet( final K from, final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.subSet( from, to ) ); }
|
|
+ public ObjectSortedSet <K> headSet( final K to ) { return new UnmodifiableSortedSet <K>( sortedSet.headSet( to ) ); }
|
|
+ public ObjectSortedSet <K> tailSet( final K from ) { return new UnmodifiableSortedSet <K>( sortedSet.tailSet( from ) ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator() { return ObjectIterators.unmodifiable( sortedSet.iterator() ); }
|
|
+ public ObjectBidirectionalIterator <K> iterator( final K from ) { return ObjectIterators.unmodifiable( sortedSet.iterator( from ) ); }
|
|
+ @Deprecated
|
|
+ public ObjectBidirectionalIterator <K> objectIterator() { return iterator(); }
|
|
+ public K first() { return sortedSet.first(); }
|
|
+ public K last() { return sortedSet.last(); }
|
|
+ }
|
|
+ /** Returns an unmodifiable type-specific sorted set backed by the given type-specific sorted set.
|
|
+ *
|
|
+ * @param s the sorted set to be wrapped in an unmodifiable sorted set.
|
|
+ * @return an unmodifiable view of the specified sorted set.
|
|
+ * @see java.util.Collections#unmodifiableSortedSet(SortedSet)
|
|
+ */
|
|
+ public static <K> ObjectSortedSet <K> unmodifiable( final ObjectSortedSet <K> s ) { return new UnmodifiableSortedSet <K>( s ); }
|
|
+}
|
|
-- |