com.meliorbis.numerics.generic.impl.BlockedArrayData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Numerics Show documentation
Show all versions of Numerics Show documentation
A library for working with large multi-dimensional arrays and the functions they represent
/**
*
*/
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();
}
}
}