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

package it.unimi.dsi.fastutil.floats;

import java.util.Arrays;
import java.io.IOException;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.FloatBuffer;

public class FloatMappedBigList extends AbstractFloatBigList
{
    public static int LOG2_BYTES;
    @Deprecated
    public static int LOG2_BITS;
    private static int CHUNK_SHIFT;
    public static final long CHUNK_SIZE;
    private static final long CHUNK_MASK;
    private final FloatBuffer[] buffer;
    private final boolean[] readyToUse;
    private final int n;
    private final long size;
    
    protected FloatMappedBigList(final FloatBuffer[] buffer, final long size, final boolean[] readyToUse) {
        this.buffer = buffer;
        this.n = buffer.length;
        this.size = size;
        this.readyToUse = readyToUse;
        for (int i = 0; i < this.n; ++i) {
            if (i < this.n - 1 && buffer[i].capacity() != FloatMappedBigList.CHUNK_SIZE) {
                throw new IllegalArgumentException();
            }
        }
    }
    
    public static FloatMappedBigList map(final FileChannel fileChannel) throws IOException {
        return map(fileChannel, ByteOrder.BIG_ENDIAN);
    }
    
    public static FloatMappedBigList map(final FileChannel fileChannel, final ByteOrder byteOrder) throws IOException {
        return map(fileChannel, byteOrder, FileChannel.MapMode.READ_ONLY);
    }
    
    public static FloatMappedBigList map(final FileChannel fileChannel, final ByteOrder byteOrder, final FileChannel.MapMode mapMode) throws IOException {
        final long size = fileChannel.size() / 4L;
        final int chunks = (int)((size + (FloatMappedBigList.CHUNK_SIZE - 1L)) / FloatMappedBigList.CHUNK_SIZE);
        final FloatBuffer[] buffer = new FloatBuffer[chunks];
        for (int i = 0; i < chunks; ++i) {
            buffer[i] = fileChannel.map(mapMode, i * FloatMappedBigList.CHUNK_SIZE * 4L, Math.min(FloatMappedBigList.CHUNK_SIZE, size - i * FloatMappedBigList.CHUNK_SIZE) * 4L).order(byteOrder).asFloatBuffer();
        }
        final boolean[] readyToUse = new boolean[chunks];
        Arrays.fill(readyToUse, true);
        return new FloatMappedBigList(buffer, size, readyToUse);
    }
    
    private FloatBuffer FloatBuffer(final int n) {
        if (this.readyToUse[n]) {
            return this.buffer[n];
        }
        this.readyToUse[n] = true;
        return this.buffer[n] = this.buffer[n].duplicate();
    }
    
    public FloatMappedBigList copy() {
        return new FloatMappedBigList(this.buffer.clone(), this.size, new boolean[this.n]);
    }
    
    @Override
    public float getFloat(final long index) {
        return this.FloatBuffer((int)(index >>> FloatMappedBigList.CHUNK_SHIFT)).get((int)(index & FloatMappedBigList.CHUNK_MASK));
    }
    
    @Override
    public void getElements(final long from, final float[] a, int offset, int length) {
        int chunk = (int)(from >>> FloatMappedBigList.CHUNK_SHIFT);
        int displ = (int)(from & FloatMappedBigList.CHUNK_MASK);
        while (length > 0) {
            final FloatBuffer b = this.FloatBuffer(chunk);
            final int l = Math.min(b.capacity() - displ, length);
            if (l == 0) {
                throw new ArrayIndexOutOfBoundsException();
            }
            b.position();
            b.get(a, offset, l);
            if ((displ += l) == FloatMappedBigList.CHUNK_SIZE) {
                displ = 0;
                ++chunk;
            }
            offset += l;
            length -= l;
        }
    }
    
    @Override
    public float set(final long index, final float value) {
        final FloatBuffer b = this.FloatBuffer((int)(index >>> FloatMappedBigList.CHUNK_SHIFT));
        final int i = (int)(index & FloatMappedBigList.CHUNK_MASK);
        final float previousValue = b.get(i);
        b.put(i, value);
        return previousValue;
    }
    
    @Override
    public long size64() {
        return this.size;
    }
    
    static {
        FloatMappedBigList.LOG2_BYTES = 63 - Long.numberOfLeadingZeros(4L);
        FloatMappedBigList.LOG2_BITS = 63 - Long.numberOfLeadingZeros(4L);
        FloatMappedBigList.CHUNK_SHIFT = 30 - FloatMappedBigList.LOG2_BYTES;
        CHUNK_SIZE = 1L << FloatMappedBigList.CHUNK_SHIFT;
        CHUNK_MASK = FloatMappedBigList.CHUNK_SIZE - 1L;
    }
}
