Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced FixedArrayFIFOQueue #296

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions drv/ArrayFIFOQueue.drv
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,19 @@ public class ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC,
return t;
}

/** Dequeues the {@linkplain PriorityQueue#last() last} element from the queue.
*
* @return the dequeued element.
* @throws NoSuchElementException if the queue is empty.
*/
@Override
public KEY_GENERIC_TYPE DEQUEUE(KEY_GENERIC_TYPE x) {
if (start == end) return x;
final KEY_GENERIC_TYPE t = array[start];
#if KEYS_REFERENCE
array[start] = null; // Clean-up for the garbage collector.
#endif
if (++start == length) start = 0;
reduce();
return t;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE_LAST() {
if (start == end) throw new NoSuchElementException();
if (end == 0) end = length;
Expand All @@ -113,6 +121,18 @@ public class ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC,
return t;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE_LAST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
if (end == 0) end = length;
final KEY_GENERIC_TYPE t = array[--end];
#if KEYS_REFERENCE
array[end] = null; // Clean-up for the garbage collector.
#endif
reduce();
return t;
}

SUPPRESS_WARNINGS_KEY_UNCHECKED
private final void resize(final int size, final int newLength) {
final KEY_GENERIC_TYPE[] newArray = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[newLength];
Expand All @@ -139,19 +159,19 @@ public class ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC,
}

@Override
public void enqueue(KEY_GENERIC_TYPE x) {
public boolean enqueue(KEY_GENERIC_TYPE x) {
array[end++] = x;
if (end == length) end = 0;
if (end == start) expand();
return true;
}

/** Enqueues a new element as the first element (in dequeuing order) of the queue.
* @param x the element to enqueue.
*/
public void enqueueFirst(KEY_GENERIC_TYPE x) {
@Override
public boolean enqueueFirst(KEY_GENERIC_TYPE x) {
if (start == 0) start = length;
array[--start] = x;
if (end == start) expand();
return true;
}

@Override
Expand All @@ -160,13 +180,25 @@ public class ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC,
return array[start];
}

@Override
public KEY_GENERIC_TYPE FIRST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
return array[start];
}


@Override
public KEY_GENERIC_TYPE LAST() {
if (start == end) throw new NoSuchElementException();
return array[(end == 0 ? length : end) - 1];
}

@Override
public KEY_GENERIC_TYPE LAST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
return array[(end == 0 ? length : end) - 1];
}

@Override
public void clear() {
#if KEYS_REFERENCE
Expand Down
32 changes: 24 additions & 8 deletions drv/ArrayPriorityQueue.drv
Original file line number Diff line number Diff line change
Expand Up @@ -154,25 +154,35 @@ public class ARRAY_PRIORITY_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENE
return this.firstIndex = firstIndex;
}

private void ensureNonEmpty() {
if (size == 0) throw new NoSuchElementException();
}

@Override
SUPPRESS_WARNINGS_KEY_UNCHECKED
public void enqueue(KEY_GENERIC_TYPE x) {
public boolean enqueue(KEY_GENERIC_TYPE x) {
if (size == array.length) array = ARRAYS.grow(array, size + 1);
if (firstIndexValid) {
if (c == null) { if (KEY_LESS(x, array[firstIndex])) firstIndex = size; }
else if (c.compare(x, array[firstIndex]) < 0) firstIndex = size;
}
else firstIndexValid = false;
array[size++] = x;
return true;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE() {
ensureNonEmpty();
if (size == 0) throw new NoSuchElementException();
final int first = findFirst();
final KEY_GENERIC_TYPE result = array[first];
System.arraycopy(array, first + 1, array, first, --size - first);
#if KEY_CLASS_Object
array[size] = null;
#endif
firstIndexValid = false;
return result;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE(KEY_GENERIC_TYPE x) {
if (size == 0) return x;
final int first = findFirst();
final KEY_GENERIC_TYPE result = array[first];
System.arraycopy(array, first + 1, array, first, --size - first);
Expand All @@ -185,13 +195,19 @@ public class ARRAY_PRIORITY_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENE

@Override
public KEY_GENERIC_TYPE FIRST() {
ensureNonEmpty();
if (size == 0) throw new NoSuchElementException();
return array[findFirst()];
}

@Override
public KEY_GENERIC_TYPE FIRST(KEY_GENERIC_TYPE x) {
if (size == 0) return x;
return array[findFirst()];
}

@Override
public void changed() {
ensureNonEmpty();
if (size == 0) throw new NoSuchElementException();
firstIndexValid = false;
}

Expand Down
221 changes: 221 additions & 0 deletions drv/FixedArrayFIFOQueue.drv
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
/*
* Copyright (C) 2010-2023 Sebastiano Vigna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


package PACKAGE;

#if KEY_CLASS_Object
import java.util.Arrays;
import java.util.Comparator;
#endif

import java.io.Serializable;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.PriorityQueue;

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.
*
* <p>This class provides additional methods that implement a <em>deque</em> (double-ended queue).
*/

public class FIXED_ARRAY_FIFO_QUEUE KEY_GENERIC implements PRIORITY_QUEUE KEY_GENERIC, Serializable {
private static final long serialVersionUID = 0L;

/** The backing array. */
protected transient KEY_GENERIC_TYPE 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.
*
* @implNote Because of inner limitations of the JVM, the initial
* capacity cannot exceed {@link it.unimi.dsi.fastutil.Arrays#MAX_ARRAY_SIZE} &minus; 1.
*
* @param capacity the initial capacity of this queue.
*/
SUPPRESS_WARNINGS_KEY_UNCHECKED
public FIXED_ARRAY_FIFO_QUEUE(final int capacity) {
if (capacity > it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE - 1) throw new IllegalArgumentException("Initial capacity (" + capacity + ") exceeds " + (it.unimi.dsi.fastutil.Arrays.MAX_ARRAY_SIZE - 1));
if (capacity < 0) throw new IllegalArgumentException("Initial capacity (" + capacity + ") is negative");
// We never build a queue with a zero-sized backing array; moreover, to
// avoid resizing at the given capacity we need one additional element.
array = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[Math.max(1, capacity + 1)];
length = array.length;
}

/** {@inheritDoc}
* @implSpec This implementation returns {@code null} (FIFO queues have no comparator). */
@Override
public KEY_COMPARATOR KEY_SUPER_GENERIC comparator() {
return null;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE() {
if (start == end) throw new NoSuchElementException();
final KEY_GENERIC_TYPE t = array[start];
#if KEYS_REFERENCE
array[start] = null; // Clean-up for the garbage collector.
#endif
if (++start == length) start = 0;
return t;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE(KEY_GENERIC_TYPE x) {
if (start == end) return x;
final KEY_GENERIC_TYPE t = array[start];
#if KEYS_REFERENCE
array[start] = null; // Clean-up for the garbage collector.
#endif
if (++start == length) start = 0;
return t;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE_LAST() {
if (start == end) throw new NoSuchElementException();
if (end == 0) end = length;
final KEY_GENERIC_TYPE t = array[--end];
#if KEYS_REFERENCE
array[end] = null; // Clean-up for the garbage collector.
#endif
return t;
}

@Override
public KEY_GENERIC_TYPE DEQUEUE_LAST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
if (end == 0) end = length;
final KEY_GENERIC_TYPE t = array[--end];
#if KEYS_REFERENCE
array[end] = null; // Clean-up for the garbage collector.
#endif
return t;
}

SUPPRESS_WARNINGS_KEY_UNCHECKED
private final void resize(final int size, final int newLength) {
final KEY_GENERIC_TYPE[] newArray = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[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;
}

@Override
public boolean enqueue(KEY_GENERIC_TYPE x) {
final int next = end++;
if (end == start) return false;
array[next] = x;
if (end == length) end = 0;
return true;
}

@Override
public boolean enqueueFirst(KEY_GENERIC_TYPE x) {
if (start == 0) start = length;
final int next = --start;
if (end == start) return false;
array[next] = x;
return true;
}

@Override
public KEY_GENERIC_TYPE FIRST() {
if (start == end) throw new NoSuchElementException();
return array[start];
}

@Override
public KEY_GENERIC_TYPE FIRST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
return array[start];
}


@Override
public KEY_GENERIC_TYPE LAST() {
if (start == end) throw new NoSuchElementException();
return array[(end == 0 ? length : end) - 1];
}

@Override
public KEY_GENERIC_TYPE LAST(KEY_GENERIC_TYPE x) {
if (start == end) return x;
return array[(end == 0 ? length : end) - 1];
}

@Override
public void clear() {
#if KEYS_REFERENCE
if (start <= end) Arrays.fill(array, start, end, null);
else {
Arrays.fill(array, start, length, null);
Arrays.fill(array, 0, end, null);
}
#endif
start = end = 0;
}

@Override
public int size() {
final int apparentLength = end - start;
return apparentLength >= 0 ? apparentLength : length + apparentLength;
}

public int capacity() {
return array.length - 1;
}

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.WRITE_KEY(array[i++]);
if (i == length) i = 0;
}
}

SUPPRESS_WARNINGS_KEY_UNCHECKED
private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
end = s.readInt();
array = KEY_GENERIC_ARRAY_CAST new KEY_TYPE[length = HashCommon.nextPowerOfTwo(end + 1)];
for(int i = 0; i < end; i++) array[i] = KEY_GENERIC_CAST s.READ_KEY();
}
}
Loading