cern.colt.matrix.AbstractMatrix3D Maven / Gradle / Ivy
Show all versions of parallelcolt Show documentation
/*
Copyright (C) 1999 CERN - European Organization for Nuclear Research.
Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose
is hereby granted without fee, provided that the above copyright notice appear in all copies and
that both that copyright notice and this permission notice appear in supporting documentation.
CERN makes no representations about the suitability of this software for any purpose.
It is provided "as is" without expressed or implied warranty.
*/
package cern.colt.matrix;
/**
* Abstract base class for 3-d matrices holding objects or primitive data types
* such as int
, double
, etc. First see the package summary and javadoc tree view to get the broad picture.
*
* Note that this implementation is not synchronized.
*
* @author [email protected]
* @version 1.0, 09/24/99
*/
public abstract class AbstractMatrix3D extends AbstractMatrix {
private static final long serialVersionUID = 1L;
/** the number of slices this matrix (view) has */
protected int slices;
/** the number of rows this matrix (view) has */
protected int rows;
/** the number of columns this matrix (view) has */
protected int columns;
/**
* the number of elements between two slices, i.e.
* index(k+1,i,j) - index(k,i,j).
*/
protected int sliceStride;
/**
* the number of elements between two rows, i.e.
* index(k,i+1,j) - index(k,i,j).
*/
protected int rowStride;
/**
* the number of elements between two columns, i.e.
* index(k,i,j+1) - index(k,i,j).
*/
protected int columnStride;
/** the index of the first element */
protected int sliceZero, rowZero, columnZero;
/**
* Makes this class non instantiable, but still let's others inherit from
* it.
*/
protected AbstractMatrix3D() {
}
/**
* Returns the position of the given absolute rank within the (virtual or
* non-virtual) internal 1-dimensional array. Default implementation.
* Override, if necessary.
*
* @param rank
* the absolute rank of the element.
* @return the position.
*/
protected int _columnOffset(int absRank) {
return absRank;
}
/**
* Returns the absolute rank of the given relative rank.
*
* @param rank
* the relative rank of the element.
* @return the absolute rank of the element.
*/
protected int _columnRank(int rank) {
return columnZero + rank * columnStride;
}
/**
* Returns the position of the given absolute rank within the (virtual or
* non-virtual) internal 1-dimensional array. Default implementation.
* Override, if necessary.
*
* @param rank
* the absolute rank of the element.
* @return the position.
*/
protected int _rowOffset(int absRank) {
return absRank;
}
/**
* Returns the absolute rank of the given relative rank.
*
* @param rank
* the relative rank of the element.
* @return the absolute rank of the element.
*/
protected int _rowRank(int rank) {
return rowZero + rank * rowStride;
}
/**
* Returns the position of the given absolute rank within the (virtual or
* non-virtual) internal 1-dimensional array. Default implementation.
* Override, if necessary.
*
* @param rank
* the absolute rank of the element.
* @return the position.
*/
protected int _sliceOffset(int absRank) {
return absRank;
}
/**
* Returns the absolute rank of the given relative rank.
*
* @param rank
* the relative rank of the element.
* @return the absolute rank of the element.
*/
protected int _sliceRank(int rank) {
return sliceZero + rank * sliceStride;
}
/**
* Checks whether the receiver contains the given box and throws an
* exception, if necessary.
*
* @throws IndexOutOfBoundsException
* if
*
* row<0 || height<0 || row+height>rows || slice<0 || depth<0 || slice+depth>slices || column<0 || width<0 || column+width>columns
*/
protected void checkBox(int slice, int row, int column, int depth, int height, int width) {
if (slice < 0 || depth < 0 || slice + depth > slices || row < 0 || height < 0 || row + height > rows
|| column < 0 || width < 0 || column + width > columns)
throw new IndexOutOfBoundsException(toStringShort() + ", slice:" + slice + ", row:" + row + " ,column:"
+ column + ", depth:" + depth + " ,height:" + height + ", width:" + width);
}
/**
* Sanity check for operations requiring a column index to be within bounds.
*
* @throws IndexOutOfBoundsException
* if column < 0 || column >= columns().
*/
protected void checkColumn(int column) {
if (column < 0 || column >= columns)
throw new IndexOutOfBoundsException("Attempted to access " + toStringShort() + " at column=" + column);
}
/**
* Checks whether indexes are legal and throws an exception, if necessary.
*
* @throws IndexOutOfBoundsException
* if ! (0 <= indexes[i] < columns()) for any
* i=0..indexes.length()-1.
*/
protected void checkColumnIndexes(int[] indexes) {
for (int i = indexes.length; --i >= 0;) {
int index = indexes[i];
if (index < 0 || index >= columns)
checkColumn(index);
}
}
/**
* Sanity check for operations requiring a row index to be within bounds.
*
* @throws IndexOutOfBoundsException
* if row < 0 || row >= rows().
*/
protected void checkRow(int row) {
if (row < 0 || row >= rows)
throw new IndexOutOfBoundsException("Attempted to access " + toStringShort() + " at row=" + row);
}
/**
* Checks whether indexes are legal and throws an exception, if necessary.
*
* @throws IndexOutOfBoundsException
* if ! (0 <= indexes[i] < rows()) for any
* i=0..indexes.length()-1.
*/
protected void checkRowIndexes(int[] indexes) {
for (int i = indexes.length; --i >= 0;) {
int index = indexes[i];
if (index < 0 || index >= rows)
checkRow(index);
}
}
/**
* Sanity check for operations requiring two matrices with the same number
* of slices, rows and columns.
*
* @throws IllegalArgumentException
* if
* slices() != B.slices() || rows() != B.rows() || columns() != B.columns()
* .
*/
public void checkShape(AbstractMatrix3D B) {
if (slices != B.slices || rows != B.rows || columns != B.columns)
throw new IllegalArgumentException("Incompatible dimensions: " + toStringShort() + " and "
+ B.toStringShort());
}
/**
* Sanity check for operations requiring matrices with the same number of
* slices, rows and columns.
*
* @throws IllegalArgumentException
* if
*
* slices() != B.slices() || rows() != B.rows() || columns() != B.columns() || slices() != C.slices() || rows() != C.rows() || columns() != C.columns()
* .
*/
public void checkShape(AbstractMatrix3D B, AbstractMatrix3D C) {
if (slices != B.slices || rows != B.rows || columns != B.columns || slices != C.slices || rows != C.rows
|| columns != C.columns)
throw new IllegalArgumentException("Incompatible dimensions: " + toStringShort() + ", " + B.toStringShort()
+ ", " + C.toStringShort());
}
/**
* Sanity check for operations requiring a slice index to be within bounds.
*
* @throws IndexOutOfBoundsException
* if slice < 0 || slice >= slices().
*/
protected void checkSlice(int slice) {
if (slice < 0 || slice >= slices)
throw new IndexOutOfBoundsException("Attempted to access " + toStringShort() + " at slice=" + slice);
}
/**
* Checks whether indexes are legal and throws an exception, if necessary.
*
* @throws IndexOutOfBoundsException
* if ! (0 <= indexes[i] < slices()) for any
* i=0..indexes.length()-1.
*/
protected void checkSliceIndexes(int[] indexes) {
for (int i = indexes.length; --i >= 0;) {
int index = indexes[i];
if (index < 0 || index >= slices)
checkSlice(index);
}
}
/**
* Returns the number of columns.
*/
public int columns() {
return columns;
}
/**
* Returns the column stride.
*/
public int columnStride() {
return columnStride;
}
/**
* Returns the position of the given coordinate within the (virtual or
* non-virtual) internal 1-dimensional array.
*
* @param slice
* the index of the slice-coordinate.
* @param row
* the index of the row-coordinate.
* @param column
* the index of the third-coordinate.
*/
public long index(int slice, int row, int column) {
return _sliceOffset(_sliceRank(slice)) + _rowOffset(_rowRank(row)) + _columnOffset(_columnRank(column));
}
/**
* Returns the number of rows.
*/
public int rows() {
return rows;
}
/**
* Returns the row stride.
*/
public int rowStride() {
return rowStride;
}
/**
* Sets up a matrix with a given number of slices and rows.
*
* @param slices
* the number of slices the matrix shall have.
* @param rows
* the number of rows the matrix shall have.
* @param columns
* the number of columns the matrix shall have.
* @throws IllegalArgumentException
* if (double)rows*slices > Integer.MAX_VALUE.
* @throws IllegalArgumentException
* if slices<0 || rows<0 || columns<0.
*/
protected void setUp(int slices, int rows, int columns) {
setUp(slices, rows, columns, 0, 0, 0, rows * columns, columns, 1);
}
/**
* Sets up a matrix with a given number of slices and rows and the given
* strides.
*
* @param slices
* the number of slices the matrix shall have.
* @param rows
* the number of rows the matrix shall have.
* @param columns
* the number of columns the matrix shall have.
* @param sliceZero
* the position of the first element.
* @param rowZero
* the position of the first element.
* @param columnZero
* the position of the first element.
* @param sliceStride
* the number of elements between two slices, i.e.
* index(k+1,i,j)-index(k,i,j).
* @param rowStride
* the number of elements between two rows, i.e.
* index(k,i+1,j)-index(k,i,j).
* @param columnnStride
* the number of elements between two columns, i.e.
* index(k,i,j+1)-index(k,i,j).
* @throws IllegalArgumentException
* if (double)slices*rows*columns > Integer.MAX_VALUE.
* @throws IllegalArgumentException
* if slices<0 || rows<0 || columns<0.
*/
protected void setUp(int slices, int rows, int columns, int sliceZero, int rowZero, int columnZero,
int sliceStride, int rowStride, int columnStride) {
if (slices < 0 || rows < 0 || columns < 0)
throw new IllegalArgumentException("negative size");
if ((double) slices * rows * columns > Integer.MAX_VALUE)
throw new IllegalArgumentException("matrix too large");
this.slices = slices;
this.rows = rows;
this.columns = columns;
this.sliceZero = sliceZero;
this.rowZero = rowZero;
this.columnZero = columnZero;
this.sliceStride = sliceStride;
this.rowStride = rowStride;
this.columnStride = columnStride;
this.isNoView = true;
}
protected int[] shape() {
int[] shape = new int[3];
shape[0] = slices;
shape[1] = rows;
shape[2] = columns;
return shape;
}
/**
* Returns the number of cells which is slices()*rows()*columns().
*/
public long size() {
return slices * rows * columns;
}
/**
* Returns the number of slices.
*/
public int slices() {
return slices;
}
/**
* Returns the slice stride.
*/
public int sliceStride() {
return sliceStride;
}
/**
* Returns a string representation of the receiver's shape.
*/
public String toStringShort() {
return AbstractFormatter.shape(this);
}
/**
* Self modifying version of viewColumnFlip().
*/
protected AbstractMatrix3D vColumnFlip() {
if (columns > 0) {
columnZero += (columns - 1) * columnStride;
columnStride = -columnStride;
this.isNoView = false;
}
return this;
}
/**
* Self modifying version of viewDice().
*
* @throws IllegalArgumentException
* if some of the parameters are equal or not in range 0..2.
*/
protected AbstractMatrix3D vDice(int axis0, int axis1, int axis2) {
int d = 3;
if (axis0 < 0 || axis0 >= d || axis1 < 0 || axis1 >= d || axis2 < 0 || axis2 >= d || axis0 == axis1
|| axis0 == axis2 || axis1 == axis2) {
throw new IllegalArgumentException("Illegal Axes: " + axis0 + ", " + axis1 + ", " + axis2);
}
// swap shape
int[] shape = shape();
this.slices = shape[axis0];
this.rows = shape[axis1];
this.columns = shape[axis2];
// swap strides
int[] strides = new int[3];
strides[0] = this.sliceStride;
strides[1] = this.rowStride;
strides[2] = this.columnStride;
this.sliceStride = strides[axis0];
this.rowStride = strides[axis1];
this.columnStride = strides[axis2];
this.isNoView = false;
return this;
}
/**
* Self modifying version of viewPart().
*
* @throws IndexOutOfBoundsException
* if
*
* slice<0 || depth<0 || slice+depth>slices() || row<0 || height<0 || row+height>rows() || column<0 || width<0 || column+width>columns()
*/
protected AbstractMatrix3D vPart(int slice, int row, int column, int depth, int height, int width) {
checkBox(slice, row, column, depth, height, width);
this.sliceZero += this.sliceStride * slice;
this.rowZero += this.rowStride * row;
this.columnZero += this.columnStride * column;
this.slices = depth;
this.rows = height;
this.columns = width;
this.isNoView = false;
return this;
}
/**
* Self modifying version of viewRowFlip().
*/
protected AbstractMatrix3D vRowFlip() {
if (rows > 0) {
rowZero += (rows - 1) * rowStride;
rowStride = -rowStride;
this.isNoView = false;
}
return this;
}
/**
* Self modifying version of viewSliceFlip().
*/
protected AbstractMatrix3D vSliceFlip() {
if (slices > 0) {
sliceZero += (slices - 1) * sliceStride;
sliceStride = -sliceStride;
this.isNoView = false;
}
return this;
}
/**
* Self modifying version of viewStrides().
*
* @throws IndexOutOfBoundsException
* if sliceStride<=0 || rowStride<=0 || columnStride<=0
* .
*/
protected AbstractMatrix3D vStrides(int sliceStride, int rowStride, int columnStride) {
if (sliceStride <= 0 || rowStride <= 0 || columnStride <= 0)
throw new IndexOutOfBoundsException("illegal strides: " + sliceStride + ", " + rowStride + ", "
+ columnStride);
this.sliceStride *= sliceStride;
this.rowStride *= rowStride;
this.columnStride *= columnStride;
if (this.slices != 0)
this.slices = (this.slices - 1) / sliceStride + 1;
if (this.rows != 0)
this.rows = (this.rows - 1) / rowStride + 1;
if (this.columns != 0)
this.columns = (this.columns - 1) / columnStride + 1;
this.isNoView = false;
return this;
}
}