// 
// Decompiled by Procyon v0.6.0
// 

package com.google.protobuf;

import java.util.Collection;
import java.util.Arrays;
import java.util.RandomAccess;

final class DoubleArrayList extends AbstractProtobufList<Double> implements Internal.DoubleList, RandomAccess, PrimitiveNonBoxingCollection
{
    private static final double[] EMPTY_ARRAY;
    private static final DoubleArrayList EMPTY_LIST;
    private double[] array;
    private int size;
    
    public static DoubleArrayList emptyList() {
        return DoubleArrayList.EMPTY_LIST;
    }
    
    DoubleArrayList() {
        this(DoubleArrayList.EMPTY_ARRAY, 0, true);
    }
    
    private DoubleArrayList(final double[] other, final int size, final boolean isMutable) {
        super(isMutable);
        this.array = other;
        this.size = size;
    }
    
    DoubleArrayList(final DoubleArrayList other, final boolean isMutable) {
        this((other.size == 0) ? DoubleArrayList.EMPTY_ARRAY : Arrays.copyOf(other.array, other.size), other.size, isMutable);
    }
    
    @Override
    protected void removeRange(final int fromIndex, final int toIndex) {
        this.ensureIsMutable();
        if (toIndex < fromIndex) {
            throw new IndexOutOfBoundsException("toIndex < fromIndex");
        }
        System.arraycopy(this.array, toIndex, this.array, fromIndex, this.size - toIndex);
        this.size -= toIndex - fromIndex;
        ++this.modCount;
    }
    
    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof DoubleArrayList)) {
            return super.equals(o);
        }
        final DoubleArrayList other = (DoubleArrayList)o;
        if (this.size != other.size) {
            return false;
        }
        final double[] arr = other.array;
        for (int i = 0; i < this.size; ++i) {
            if (Double.doubleToLongBits(this.array[i]) != Double.doubleToLongBits(arr[i])) {
                return false;
            }
        }
        return true;
    }
    
    @Override
    public int hashCode() {
        int result = 1;
        for (int i = 0; i < this.size; ++i) {
            final long bits = Double.doubleToLongBits(this.array[i]);
            result = 31 * result + Internal.hashLong(bits);
        }
        return result;
    }
    
    @Override
    public Internal.DoubleList mutableCopyWithCapacity(final int capacity) {
        if (capacity < this.size) {
            throw new IllegalArgumentException();
        }
        final double[] newArray = (capacity == 0) ? DoubleArrayList.EMPTY_ARRAY : Arrays.copyOf(this.array, capacity);
        return new DoubleArrayList(newArray, this.size, true);
    }
    
    @Override
    public Double get(final int index) {
        return this.getDouble(index);
    }
    
    @Override
    public double getDouble(final int index) {
        this.ensureIndexInRange(index);
        return this.array[index];
    }
    
    @Override
    public int indexOf(final Object element) {
        if (!(element instanceof Double)) {
            return -1;
        }
        final double unboxedElement = (double)element;
        for (int numElems = this.size(), i = 0; i < numElems; ++i) {
            if (this.array[i] == unboxedElement) {
                return i;
            }
        }
        return -1;
    }
    
    @Override
    public boolean contains(final Object element) {
        return this.indexOf(element) != -1;
    }
    
    @Override
    public int size() {
        return this.size;
    }
    
    @Override
    public Double set(final int index, final Double element) {
        return this.setDouble(index, element);
    }
    
    @Override
    public double setDouble(final int index, final double element) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final double previousValue = this.array[index];
        this.array[index] = element;
        return previousValue;
    }
    
    @Override
    public boolean add(final Double element) {
        this.addDouble(element);
        return true;
    }
    
    @Override
    public void add(final int index, final Double element) {
        this.addDouble(index, element);
    }
    
    @Override
    public void addDouble(final double element) {
        this.ensureIsMutable();
        if (this.size == this.array.length) {
            final int length = growSize(this.array.length);
            final double[] newArray = new double[length];
            System.arraycopy(this.array, 0, newArray, 0, this.size);
            this.array = newArray;
        }
        this.array[this.size++] = element;
    }
    
    private void addDouble(final int index, final double element) {
        this.ensureIsMutable();
        if (index < 0 || index > this.size) {
            throw new IndexOutOfBoundsException(this.makeOutOfBoundsExceptionMessage(index));
        }
        if (this.size < this.array.length) {
            System.arraycopy(this.array, index, this.array, index + 1, this.size - index);
        }
        else {
            final int length = growSize(this.array.length);
            final double[] newArray = new double[length];
            System.arraycopy(this.array, 0, newArray, 0, index);
            System.arraycopy(this.array, index, newArray, index + 1, this.size - index);
            this.array = newArray;
        }
        this.array[index] = element;
        ++this.size;
        ++this.modCount;
    }
    
    @Override
    public boolean addAll(final Collection<? extends Double> collection) {
        this.ensureIsMutable();
        Internal.checkNotNull(collection);
        if (!(collection instanceof DoubleArrayList)) {
            return super.addAll(collection);
        }
        final DoubleArrayList list = (DoubleArrayList)collection;
        if (list.size == 0) {
            return false;
        }
        final int overflow = Integer.MAX_VALUE - this.size;
        if (overflow < list.size) {
            throw new OutOfMemoryError();
        }
        final int newSize = this.size + list.size;
        if (newSize > this.array.length) {
            this.array = Arrays.copyOf(this.array, newSize);
        }
        System.arraycopy(list.array, 0, this.array, this.size, list.size);
        this.size = newSize;
        ++this.modCount;
        return true;
    }
    
    @Override
    public Double remove(final int index) {
        this.ensureIsMutable();
        this.ensureIndexInRange(index);
        final double value = this.array[index];
        if (index < this.size - 1) {
            System.arraycopy(this.array, index + 1, this.array, index, this.size - index - 1);
        }
        --this.size;
        ++this.modCount;
        return value;
    }
    
    void ensureCapacity(final int minCapacity) {
        if (minCapacity <= this.array.length) {
            return;
        }
        if (this.array.length == 0) {
            this.array = new double[Math.max(minCapacity, 10)];
            return;
        }
        int n;
        for (n = this.array.length; n < minCapacity; n = growSize(n)) {}
        this.array = Arrays.copyOf(this.array, n);
    }
    
    private static int growSize(final int previousSize) {
        return Math.max(previousSize * 3 / 2 + 1, 10);
    }
    
    private void ensureIndexInRange(final int index) {
        if (index < 0 || index >= this.size) {
            throw new IndexOutOfBoundsException(this.makeOutOfBoundsExceptionMessage(index));
        }
    }
    
    private String makeOutOfBoundsExceptionMessage(final int index) {
        return "Index:" + index + ", Size:" + this.size;
    }
    
    static {
        EMPTY_ARRAY = new double[0];
        EMPTY_LIST = new DoubleArrayList(DoubleArrayList.EMPTY_ARRAY, 0, false);
    }
}
