All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.meliorbis.numerics.generic.impl.BlockedArrayData Maven / Gradle / Ivy

Go to download

A library for working with large multi-dimensional arrays and the functions they represent

There is a newer version: 1.2
Show newest version
/**
 * 
 */
package com.meliorbis.numerics.generic.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.meliorbis.numerics.generic.MultiDimensionalArrayException;
import com.meliorbis.numerics.generic.ParallelIterator;
import com.meliorbis.numerics.generic.SettableIndexedIterator;
import com.meliorbis.numerics.generic.SettableIterator;
import com.meliorbis.numerics.generic.SubSpaceSplitIterator;
import com.meliorbis.numerics.index.Index;
import com.meliorbis.numerics.index.IndexIterator;
import com.meliorbis.numerics.index.SkippingLinearIterator;
import com.meliorbis.numerics.index.SubIndex;
import com.meliorbis.numerics.index.SubIndexIterator;

/**
 * Holds data for a multidimensional array
 * 
 * @author Tobias Grasl
 */
public abstract class BlockedArrayData
{
	protected static final int DEFAULT_BLOCK_SIZE = 10000;

	final protected int _blockSize;
    final protected int _numBlocks;

    final protected Index _logicalIndex;
    final protected Index _physicalIndex;

    protected BlockedArrayData(int[] dimensions_)
    {
        this(DEFAULT_BLOCK_SIZE, dimensions_);
    }

    protected BlockedArrayData(int blockSize_, int[] dimensions_)
    {
        _logicalIndex = new com.meliorbis.numerics.index.impl.Index(dimensions_);
        _blockSize = blockSize_;

        int size = _logicalIndex.numberOfElements();

        _numBlocks = size/_blockSize+1;

        _physicalIndex = new com.meliorbis.numerics.index.impl.Index(_numBlocks,_blockSize);
    }

    protected abstract T get(int block_, int index_);
    protected abstract void set(int i, int i1, T val_);


    protected int[] logicalToPhysical(int[] indices_) throws MultiDimensionalArrayException
	{
		int linearIndex = logicalToLinear(indices_);

		int[] fakeIndex = linearToPhysical(linearIndex);
		
		return fakeIndex;
	}

	protected int[] linearToPhysical(int linearIndex_)
	{
		return _physicalIndex.toLogicalIndex(linearIndex_);
	}
	
	protected int logicalToLinear(int... indices_) throws MultiDimensionalArrayException
	{
		try
		{
			return _logicalIndex.toLinearIndex(indices_);
		} catch (IndexOutOfBoundsException e)
		{
			throw new MultiDimensionalArrayException(e);
		}
	}
	
	private int numberOfElements()
	{
		return _logicalIndex.numberOfElements();
	}
	
	/**
	 * The size of a block depends on its index. All blocks bar the last are of size BLOCK_SIZE. The final
	 * block just holds the remaining values, so could be smaller
	 * 
	 * @param blockNum_ The index of the block of which to return the size
	 * 
	 * @return The size of the indicated block
	 */
    protected int getBlockSize(int blockNum_)
	{
		return blockNum_ == (_numBlocks-1) ? (((numberOfElements()-1) % _blockSize)+1): _blockSize;
	}
	
	public Index getLogicalIndex()
	{
		return _logicalIndex;
	}
	
	final protected SubSpaceSplitIterator iteratorAt(int... index_)
	{
        final com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator logicalIterator = (com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator) _logicalIndex.iteratorAt(index_);
        return createSubSpacedIterator(logicalIterator);
	}

    protected BlockedDataSubSpaceSplitIterator createSubSpacedIterator(SubIndexIterator logicalIterator_)
    {
        return new BlockedDataSubSpaceSplitIterator(logicalIterator_);
    }

    final protected List> parallelIterators(int... dimensions_)
    {
        return wrapIterators(_logicalIndex.parallelIterators(5, dimensions_));
    }

    private  List> wrapIterators(SkippingLinearIterator[] indexIterators_)
    {
        final List> dataIterators = new ArrayList>(indexIterators_.length);               

        for (int i = 0; i < indexIterators_.length; i++)
        {
            final SkippingLinearIterator indexIterator = indexIterators_[i];
            dataIterators.add(createBlockedDataSettableIterator(indexIterator));
        }

        return dataIterators;
    }

    protected BlockedDataSettableIterator createBlockedDataSettableIterator(SkippingLinearIterator indexIterator_)
    {
        return new BlockedDataSettableIterator(indexIterator_);
    }

    public List> parallelIterators(SubIndex subIndex_, int[] dimensions_)
    {
        return wrapIterators(subIndex_.parallelIterators(1, dimensions_));
    }

	protected SubSpaceSplitIterator iteratorAcross(int... dimensions_)
	{
		return createSubSpacedIterator(_logicalIndex.iterator(dimensions_));
	}
	
	protected SubSpaceSplitIterator iteratorAcross(SubIndex subIndex_, int[] dimensions_)
	{
		com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator iterator = (com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator) subIndex_.iterator(dimensions_);
		return createSubSpacedIterator(iterator);
	}
	

	public SubSpaceSplitIterator iteratorAt(SubIndex subIndex_, int[] index_)
	{
		com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator iterator = (com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator) subIndex_.iteratorAt(index_);
		return createSubSpacedIterator(iterator);
	}

	public SettableIndexedIterator iteratorAcross(
			Index subIndex_) {
		return createSubSpacedIterator((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator) subIndex_.iterator());
	}
	
	protected SettableIndexedIterator iterator()
	{
		return new BlockedDataIterator();
	}

    protected SettableIndexedIterator rangeIterator(int from_, int to_)
    {
        return new BlockedDataIterator(from_, to_);
    }

    final public SettableIndexedIterator rangeIterator(SubIndex subIndex_, int from_, int to_)
    {
        return createSubSpacedIterator(subIndex_.rangeIterator(from_, to_));
    }

    protected class BlockedDataIterator implements SettableIndexedIterator
	{
		protected IndexIterator _iterator;
		protected int _count = -1;
		
		protected BlockedDataIterator()
		{
			_iterator = _physicalIndex.iterator();
		}

        protected BlockedDataIterator(int from_, int to_)
        {
            _iterator = _physicalIndex.rangeIterator(from_, to_);
        }

        @Override
		public boolean hasNext()
		{
			return (_count < _logicalIndex.numberOfElements()-1) && _iterator.hasNext();
		}

		@Override
		public T next()
		{
			// need to keep track of the number of elements
			// because the physical iterator doesn't know
			// when to stop
			_count = _iterator.nextInt();
			
			return get();
		}

		@Override
		public void remove()
		{
			throw new UnsupportedOperationException("'remove' not implemented");
		}

		@Override
		final public T get()
		{
			int[] index = _iterator.getCurrentIndex();
			
			return BlockedArrayData.this.get(index[0],index[1]);
		}

		@Override
		public void set(T val_)
		{
			int[] index = _iterator.getCurrentIndex();
			
			BlockedArrayData.this.set(index[0],index[1],val_);
		}

		@Override
		public int[] getIndex()
		{
			return _logicalIndex.toLogicalIndex(_physicalIndex.toLinearIndex(_iterator.getCurrentIndex()));
		}

		@Override
		public void reset()
		{
			_iterator.reset();
		}
	}

    protected class BlockedDataSettableIterator implements SettableIterator, ParallelIterator
    {
        protected final SkippingLinearIterator _indexIterator;
        protected final int[] _physIndex = new int[2];

        protected BlockedDataSettableIterator(SkippingLinearIterator indexIterator_)
        {
            _indexIterator = indexIterator_;
        }


        @Override
        public boolean hasNext() {
            return  _indexIterator.hasNext();
        }

        @Override
        public T next() {

            if (!moveToNext())
            {
                return null;
            }

            return getCurrent();
        }

        protected boolean moveToNext()
        {
            // need to keep track of the number of elements
            // because the physical iterator doesn't know
            // when to stop
            _indexIterator.nextInt();

            calcPhysical();

            // Always succeeds
            return true;
        }

		private void calcPhysical()
		{
			_physIndex[0] = _indexIterator.getCurrentFullLinearIndex()/_blockSize;
            _physIndex[1] = _indexIterator.getCurrentFullLinearIndex()%_blockSize;
		}

        T getCurrent() {
            return BlockedArrayData.this.get(_physIndex[0], _physIndex[1]);
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("Remove not implemented");
        }

        @Override
        public T get() {
            return getCurrent();
        }

        @Override
        public void set(T val_) {
            BlockedArrayData.this.set(_physIndex[0],_physIndex[1],val_);
        }


		@Override
		public boolean hasNextParallel()
		{
			return _indexIterator.hasNextParallel();
		}


		@Override
		public int nextParallel()
		{
			return _indexIterator.nextParallel();
		}


		@Override
		public void reset()
		{
			_indexIterator.reset();
			Arrays.fill(_physIndex, 0);
		}


		@Override
		public int parallelCount()
		{
			return ((com.meliorbis.numerics.index.impl.Index.ParallelIterator)_indexIterator).getNumParallel();
		}
    }



    protected class BlockedDataSubSpaceSplitIterator extends BlockedDataSettableIterator
            implements SubSpaceSplitIterator
	{
		protected BlockedDataSubSpaceSplitIterator(SubIndexIterator logicalIterator_)
		{
            super(logicalIterator_);
		}

        @Override
        protected boolean moveToNext()
        {
            // need to keep track of the number of elements
            // because the physical iterator doesn't know
            // when to stop
            _indexIterator.nextInt();

            // If the orthogonal iterator has not started yet then there is nothing to return
            if(!((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).orthStarted())
            {
                return false;
            }

            _physIndex[0] = _indexIterator.getCurrentFullLinearIndex()/_blockSize;
            _physIndex[1] = _indexIterator.getCurrentFullLinearIndex()%_blockSize;

            return true;
        }

        @Override
		public int[] getIndex() {
			return ((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).getCurrentIndex();
		}

		@Override
		public SubSpaceSplitIterator getOrthogonalIterator() {
			// Create an orthogonal iterator
			return new BlockedDataSubSpaceSplitIterator(((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).getOrthogonalIterator());
		}

		@Override
		public int[] getFullIndex() {
			return ((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).getCurrentFullIndex();
		}

		@Override
		public int[] getSizes() {
			return ((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).getSizes();
		}

		@Override
		public int[] getOtherIndex() {
			return ((com.meliorbis.numerics.index.impl.Index.SubSpaceSplitIterator)_indexIterator).getOtherIndex();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy