Subversion Repositories splitter

Rev

Rev 163 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package uk.me.parabola.splitter;

import it.unimi.dsi.bits.Fast;
import it.unimi.dsi.fastutil.ints.Int2ShortFunction;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.shorts.ShortArrayList;

public class SparseInt2ShortMap  implements Int2ShortFunction {
        static final int CHUNK_SIZE = 64; // MUST be <= 64.
        static final int SIZE_INCR = 65536;
        /** What to return on unassigned indices */
        short unassigned = -1;
       
        ObjectArrayList<ShortArrayList> valschunks;
        LongArrayList bitmasks;
        int capacity;
        int size;
        int lastTrim = 0;

       
        SparseInt2ShortMap() {
                clear();
        }
       
        void resizeTo(int key) {
                //for (int i = lastTrim ; i < capacity ; i += CHUNK_SIZE) {
                //      ShortArrayList tmp = valschunks.get(i/CHUNK_SIZE);
                //      if (tmp != null)
                //              valschunks.get(i/CHUNK_SIZE).trim();
                //}
                lastTrim = capacity;
               
                if (key <= capacity)
                        return;
                capacity = key + key/8 + SIZE_INCR;
                bitmasks.size(1+capacity/CHUNK_SIZE);
                valschunks.size(1+capacity/CHUNK_SIZE);
        }

        /** Count how many of the lowest X bits in mask are set
         * @return */

        int countUnder(long mask, int lowest) {
                return Fast.count(mask & ((1L << lowest) -1));
        }
       
        public boolean containsKey(int key) {
                int chunkid = key/CHUNK_SIZE;
                int chunkoffset = key%CHUNK_SIZE;
                if (chunkid >= valschunks.size())
                        return false;
                long chunkmask = bitmasks.get(chunkid);
                long elementmask = 1L << chunkoffset;
                return (chunkmask & elementmask) != 0;
        }
       
        public short put(int key, short val) {
                if (val == unassigned) {
                        throw new IllegalArgumentException("Cannot store the value that is reserved as being unassigned. val="+val);
                }
                if (key < 0) {
                        throw new IllegalArgumentException("Cannot store the negative key,"+key);
                }

                resizeTo(key);
                int chunkid = key/CHUNK_SIZE;
                int chunkoffset = key%CHUNK_SIZE;
                if (valschunks.get(chunkid) == null)
                        valschunks.set(chunkid, new ShortArrayList(1));
                ShortArrayList chunk = valschunks.get(chunkid);
                long chunkmask = bitmasks.get(chunkid);
                long elementmask = 1L << chunkoffset;
                if ((chunkmask & elementmask) != 0) {
                        // Already in the array, find the offset and store.
                        short out = chunk.get(countUnder(chunkmask,chunkoffset));
                        chunk.set(countUnder(chunkmask,chunkoffset), val);
                        //System.out.println("Returning found key "+out+" from put "+ key + " " + val);
                        return out;
                } else {
                        size++;
                        // Not in the array. Time to insert.
                        int offset = countUnder(chunkmask,chunkoffset);
                        chunk.add(offset,val);
                        bitmasks.set(chunkid, elementmask | chunkmask);
                        //System.out.println("Returning unassigned from put "+ key + " " + val);
                        return unassigned;
                }
        }

        public short get(int key) {
                int chunkid = key/CHUNK_SIZE;
                int chunkoffset = key%CHUNK_SIZE;
                if (key <= 0 || chunkid >= valschunks.size())
                        return unassigned;
                ShortArrayList chunk = valschunks.get(chunkid);
                long chunkmask = bitmasks.get(chunkid);
                long elementmask = 1L << chunkoffset;
                if ((chunkmask & elementmask) == 0) {
                        return unassigned;
                } else {
                        return chunk.get(countUnder(chunkmask,chunkoffset));
                }
        }

        public short remove(int key) {
                int chunkid = key/CHUNK_SIZE;
                int chunkoffset = key%CHUNK_SIZE;
                if (chunkid >= valschunks.size())
                        return unassigned;
                ShortArrayList chunk = valschunks.get(chunkid);
                long chunkmask = bitmasks.get(chunkid);
                long elementmask = 1L << chunkoffset;
                if ((chunkmask & elementmask) == 0) {
                        // Not in the array.
                        // Do nothing;
                        return unassigned;
                } else {
                        size--;
                        // In the array. Time to insert.
                        int offset = countUnder(chunkmask,chunkoffset);
                        short out = chunk.get(offset);
                        chunk.rem(offset);
                        bitmasks.set(chunkid, (~elementmask) & chunkmask);
                        return out;
                }              
        }

        @Override
        public void clear() {
                valschunks = new ObjectArrayList<ShortArrayList>();
                bitmasks = new LongArrayList();
                capacity = 0;
                size = 0;
        }

        @Override
        public boolean containsKey(Object arg0) {
                throw new UnsupportedOperationException("TODO: Implement");
        }

        @Override
        public Short get(Object arg0) {
                throw new UnsupportedOperationException("TODO: Implement");
        }

        @Override
        public Short put(Integer arg0, Short arg1) {
                return put(arg0.intValue(),arg1.shortValue());
        }

        @Override
        public Short remove(Object arg0) {
                throw new UnsupportedOperationException("TODO: Implement");
        }

        @Override
        public int size() {
                return size;
        }

        @Override
        public short defaultReturnValue() {
                return unassigned;
        }

        @Override
        public void defaultReturnValue(short arg0) {
                unassigned = arg0;
        }
}