/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package hivemall.utils.collections;
import hivemall.utils.lang.Preconditions;
import java.util.Iterator;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;
@NotThreadSafe
public final class DoubleRingBuffer implements Iterable<Double> {
private final double[] ring;
private final int capacity;
private int size;
private int head;
public DoubleRingBuffer(int capacity) {
this.ring = new double[capacity];
this.capacity = capacity;
this.size = 0;
this.head = 0;
}
@Nonnull
public double[] getRing() {
return ring;
}
public int capacity() {
return capacity;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean isFull() {
return size == capacity;
}
public DoubleRingBuffer add(final double x) {
ring[head] = x;
head = (head + 1) % capacity;
if (size != capacity) {
size++;
}
return this;
}
public void toArray(@Nonnull final double[] dst) {
toArray(dst, true);
}
public void toArray(@Nonnull final double[] dst, final boolean fifo) {
Preconditions.checkArgument(dst.length == capacity);
if (fifo) {
int curr = isFull() ? head : 0;
for (int i = 0; i < capacity; i++) {
dst[i] = ring[curr];
curr = (curr + 1) % capacity;
}
} else {
int curr = isFull() ? head : 0;
for (int i = 1; i <= size; i++) {
dst[size - i] = ring[curr];
curr = (curr + 1) % capacity;
}
for (int i = size; i < capacity; i++) {
dst[i] = 0;
}
}
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(128);
buf.append('{');
int curr = isFull() ? head : 0;
for (int i = 0; i < capacity; i++) {
if (i != 0) {
buf.append(',');
}
buf.append(ring[curr]);
curr = (curr + 1) % capacity;
}
buf.append('}');
return buf.toString();
}
@Override
public Iterator<Double> iterator() {
return new Itor();
}
private final class Itor implements Iterator<Double> {
private int curr;
private int i;
Itor() {
this.curr = isFull() ? head : 0;
this.i = 0;
}
@Override
public boolean hasNext() {
return i < capacity;
}
@Override
public Double next() {
Double d = ring[curr];
curr = (curr + 1) % capacity;
i++;
return d;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
}