mikera.arrayz.Array Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vectorz Show documentation
Show all versions of vectorz Show documentation
Fast double-precision vector and matrix maths library for Java, supporting N-dimensional numeric arrays.
package mikera.arrayz;
import java.nio.DoubleBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import mikera.arrayz.impl.BaseShapedArray;
import mikera.arrayz.impl.IDenseArray;
import mikera.arrayz.impl.IStridedArray;
import mikera.arrayz.impl.ImmutableArray;
import mikera.indexz.Index;
import mikera.matrixx.Matrix;
import mikera.vectorz.AVector;
import mikera.vectorz.IOperator;
import mikera.vectorz.Op;
import mikera.vectorz.Op2;
import mikera.vectorz.Scalar;
import mikera.vectorz.Tools;
import mikera.vectorz.Vector;
import mikera.vectorz.Vectorz;
import mikera.vectorz.impl.ArrayIndexScalar;
import mikera.vectorz.impl.StridedElementIterator;
import mikera.vectorz.util.DoubleArrays;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.IntArrays;
import mikera.vectorz.util.VectorzException;
/**
* General purpose, mutable, packed, dense N-dimensional array
*
* This is the general multi-dimensional equivalent of Matrix and Vector, and as such is the
* most efficient storage type for dense 3D+ arrays
*
* @author Mike
*
*/
public final class Array extends BaseShapedArray implements IStridedArray, IDenseArray {
private static final long serialVersionUID = -8636720562647069034L;
private final int dimensions;
private final int[] strides;
private final double[] data;
private Array(int dims, int[] shape, int[] strides) {
super(shape);
this.dimensions = dims;
this.strides = strides;
int n = (int) IntArrays.arrayProduct(shape);
this.data = new double[n];
}
private Array(int[] shape, double[] data) {
this(shape.length, shape, IntArrays.calcStrides(shape), data);
}
private Array(int dims, int[] shape, double[] data) {
this(dims, shape, IntArrays.calcStrides(shape), data);
}
/**
* Wraps double[] array data in an Array of the specified shape.
*
* The number of elements in the array must exactly match the length of the array.
*
* @param data
* @param shape
* @return
*/
public static Array wrap(double[] data, int... shape) {
long ec=IntArrays.arrayProduct(shape);
if (data.length!=ec) throw new IllegalArgumentException("Data array does not have correct number of elements, expected: "+ec);
return new Array(shape.length,shape,data);
}
private Array(int dims, int[] shape, int[] strides, double[] data) {
super(shape);
this.dimensions = dims;
this.strides = strides;
this.data = data;
}
/**
* Wraps the underlying data from a dense Vector as an array with the same shape
* @param v
* @return
*/
public static Array wrap(Vector v) {
return new Array(v.getShapeClone(),v.getArray());
}
/**
* Wraps the underlying data from a dense Matrix as an array with the same shape
* @param v
* @return
*/
public static Array wrap(Matrix m) {
return new Array(m.getShapeClone(),m.getArray());
}
/**
* Creates a new zero-filled mutable Array of the specified shape.
* @param shape
* @return
*/
public static Array newArray(int... shape) {
return new Array(shape.length, shape.clone(), DoubleArrays.createStorageArray(shape));
}
/**
* Crates a new Array with a copy of the data from the specified array, in the same shape
* @param a
* @return
*/
public static Array create(INDArray a) {
int[] shape=a.getShapeClone();
return new Array(a.dimensionality(), shape, a.toDoubleArray());
}
@Override
public int dimensionality() {
return dimensions;
}
@Override
protected final void checkDimension(int dimension) {
if ((dimension < 0) || (dimension >= dimensions))
throw new IndexOutOfBoundsException(ErrorMessages.invalidDimension(this,dimension));
}
@Override
public long[] getLongShape() {
long[] lshape = new long[dimensions];
IntArrays.copyIntsToLongs(shape, lshape);
return lshape;
}
@Override
public int getStride(int dim) {
return strides[dim];
}
/**
* Computes the array index of the specified index position in the underlyind data array
* @param indexes
* @return
*/
protected int getIndex(int... indexes) {
int ix = 0;
for (int i = 0; i < dimensions; i++) {
ix += indexes[i] * getStride(i);
}
return ix;
}
@Override
public double get(int... indexes) {
return data[getIndex(indexes)];
}
@Override
public void set(int[] indexes, double value) {
data[getIndex(indexes)] = value;
}
@Override
public Vector asVector() {
return Vector.wrap(data);
}
@Override
public Vector toVector() {
return Vector.create(data);
}
@Override
public INDArray slice(int majorSlice) {
return slice(0, majorSlice);
}
@Override
public INDArray slice(int dimension, int index) {
Arrayz.checkShape(this,dimension,index);
if (dimensions == 1) return ArrayIndexScalar.wrap(data, index);
if (dimensions == 2) {
if (dimension == 0) {
return Vectorz.wrap(data, index * shape[1], shape[1]);
} else {
return Vectorz.wrapStrided(data, index, shape[0], strides[0]);
}
}
int offset = index * getStride(dimension);
return Arrayz.wrapStrided(
data,
offset,
IntArrays.removeIndex(shape, dimension),
IntArrays.removeIndex(strides, dimension));
}
@Override
public INDArray getTranspose() {
return getTransposeView();
}
@Override
public INDArray getTransposeView() {
return NDArray.wrapStrided(data, 0, IntArrays.reverse(shape), IntArrays.reverse(strides));
}
@Override
public INDArray subArray(int[] offsets, int[] shape) {
int n=dimensions;
if (offsets.length!=n) throw new IllegalArgumentException(ErrorMessages.invalidIndex(this, offsets));
if (shape.length!=n) throw new IllegalArgumentException(ErrorMessages.invalidIndex(this, offsets));
// check if we can return the whole array
if (IntArrays.equals(shape, this.shape)) {
if (IntArrays.isZero(offsets)) {
return this;
} else {
throw new IllegalArgumentException("Invalid subArray offsets");
}
}
int[] strides=IntArrays.calcStrides(this.shape);
return new NDArray(data,
IntArrays.dotProduct(offsets, strides),
IntArrays.copyOf(shape),
strides);
}
@Override
public long elementCount() {
return data.length;
}
@Override
public double elementSum() {
return DoubleArrays.elementSum(data);
}
@Override
public double elementMax(){
return DoubleArrays.elementMax(data);
}
@Override
public double elementMin(){
return DoubleArrays.elementMin(data);
}
@Override
public double elementSquaredSum() {
return DoubleArrays.elementSquaredSum(data);
}
@Override
public void abs() {
DoubleArrays.abs(data);
}
@Override
public void signum() {
DoubleArrays.signum(data);
}
@Override
public void square() {
DoubleArrays.square(data);
}
@Override
public void exp() {
DoubleArrays.exp(data);
}
@Override
public void log() {
DoubleArrays.log(data);
}
@Override
public boolean isMutable() {
return true;
}
@Override
public boolean isFullyMutable() {
return true;
}
@Override
public boolean isElementConstrained() {
return false;
}
@Override
public boolean isView() {
return false;
}
@Override
public void applyOp(Op op) {
op.applyTo(data);
}
@Override
public double reduce(Op2 op) {
return DoubleArrays.reduce(op, data, 0, data.length);
}
@Override
public double reduce(Op2 op, double init) {
return op.reduce(init, data, 0, data.length);
}
@Override
public void applyOp(IOperator op) {
if (op instanceof Op) {
((Op) op).applyTo(data);
} else {
for (int i = 0; i < data.length; i++) {
data[i] = op.apply(data[i]);
}
}
}
@Override
public boolean equals(INDArray a) {
if (!isSameShape(a)) return false;
return a.equalsArray(data, 0);
}
@Override
public Array exactClone() {
return new Array(dimensions, shape, strides, data.clone());
}
@Override
public void setElements(int pos, double[] values, int offset, int length) {
System.arraycopy(values, offset, data, pos, length);
}
@Override
public void getElements(double[] values, int offset) {
System.arraycopy(data, 0, values, offset, data.length);
}
@Override
public Iterator elementIterator() {
return new StridedElementIterator(data,0,(int)elementCount(),1);
}
@Override
public void multiply(double factor) {
DoubleArrays.multiply(data, 0, data.length, factor);
}
@Override
public List> getSlices() {
if (dimensions==1) {
int n=sliceCount();
ArrayList al=new ArrayList(n);
for (int i=0; i 0) && (strides[dimensions - 1] != 1))
throw new VectorzException("Last stride should be 1");
if (data.length != IntArrays.arrayProduct(shape))
throw new VectorzException("Inconsistent shape");
if (!IntArrays.equals(strides, IntArrays.calcStrides(shape)))
throw new VectorzException("Inconsistent strides");
}
/**
* Creates a new matrix using the elements in the specified vector.
* Truncates or zero-pads the data as required to fill the new matrix
* @param data
* @param rows
* @param columns
* @return
*/
public static Array createFromVector(AVector a, int... shape) {
Array m = Array.newArray(shape);
int n=(int)Math.min(m.elementCount(), a.length());
a.copyTo(0, m.data, 0, n);
return m;
}
@Override
public double[] getArray() {
return data;
}
@Override
public int getArrayOffset() {
return 0;
}
@Override
public int[] getStrides() {
return strides;
}
@Override
public boolean isPackedArray() {
return true;
}
@Override
public boolean isZero() {
return DoubleArrays.isZero(data);
}
@Override
public INDArray immutable() {
return ImmutableArray.wrap(DoubleArrays.copyOf(data), this.shape);
}
@Override
public double get() {
if (dimensions==0) {
return data[0];
} else {
throw new IllegalArgumentException("O-d get not supported on Array of shape: "+Index.of(this.getShape()).toString());
}
}
@Override
public double get(int x) {
if (dimensions==1) {
return data[x];
} else {
throw new IllegalArgumentException("1-d get not supported on Array of shape: "+Index.of(this.getShape()).toString());
}
}
@Override
public double get(int x, int y) {
if (dimensions==2) {
return data[x*strides[0]+y];
} else {
throw new IllegalArgumentException("2-d get not supported on Array of shape: "+Index.of(this.getShape()).toString());
}
}
@Override
public boolean equalsArray(double[] data, int offset) {
return DoubleArrays.equals(this.data, 0, data, offset, Tools.toInt(elementCount()));
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy