Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.nd4j.linalg.api.complex;
import static org.nd4j.linalg.util.ArrayUtil.calcStrides;
import static org.nd4j.linalg.util.ArrayUtil.calcStridesFortran;
import static org.nd4j.linalg.util.ArrayUtil.reverseCopy;
import org.nd4j.linalg.api.buffer.DataBuffer;
import org.nd4j.linalg.api.ndarray.BaseNDArray;
import org.nd4j.linalg.api.ndarray.DimensionSlice;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.api.ndarray.SliceOp;
import org.nd4j.linalg.factory.NDArrayFactory;
import org.nd4j.linalg.factory.Nd4j;
import org.nd4j.linalg.indexing.conditions.Condition;
import org.nd4j.linalg.indexing.Indices;
import org.nd4j.linalg.indexing.NDArrayIndex;
import org.nd4j.linalg.ops.reduceops.Ops;
import org.nd4j.linalg.ops.reduceops.complex.ComplexOps;
import org.nd4j.linalg.ops.transforms.Transforms;
import org.nd4j.linalg.util.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
/**
* ComplexNDArray for complex numbers.
*
*
* Note that the indexing scheme for a complex ndarray is 2 * length
* not length.
*
* The reason for this is the fact that imaginary components have
* to be stored alongside realComponent components.
*
* @author Adam Gibson
*/
public abstract class BaseComplexNDArray extends BaseNDArray implements IComplexNDArray {
public BaseComplexNDArray() {}
public BaseComplexNDArray(DataBuffer data, int[] shape, int[] stride) {
this(data,shape,stride,0,Nd4j.order());
}
public BaseComplexNDArray(float[] data) {
super(data);
}
public BaseComplexNDArray(DataBuffer buffer,int[] shape,int[] stride,int offset,char ordering) {
super(buffer,shape,stride,offset,ordering);
}
/**
* Create this ndarray with the given data and shape and 0 offset
*
* @param data the data to use
* @param shape the shape of the ndarray
* @param ordering
*/
public BaseComplexNDArray(float[] data, int[] shape, char ordering) {
this(data,shape, Nd4j.getComplexStrides(shape, ordering),0,ordering);
}
public BaseComplexNDArray(int[] shape, int offset, char ordering) {
this(Nd4j.createBuffer(ArrayUtil.prod(shape) * 2),
shape, Nd4j.getComplexStrides(shape, ordering),
offset,ordering);
}
public BaseComplexNDArray(int[] shape) {
this(Nd4j.createBuffer(ArrayUtil.prod(shape) * 2),shape, Nd4j.getComplexStrides(shape));
}
public BaseComplexNDArray(float[] data, int[] shape, int[] stride, char ordering) {
this(data,shape,stride,0,ordering);
}
public BaseComplexNDArray(int[] shape, char ordering) {
this(Nd4j.createBuffer(ArrayUtil.prod(shape) * 2),shape, Nd4j.getComplexStrides(shape, ordering),0,ordering);
}
/**
* Initialize the given ndarray as the real component
* @param m the real component
* @param stride the stride of the ndarray
* @param ordering the ordering for the ndarray
*/
public BaseComplexNDArray(INDArray m,int[] stride,char ordering) {
this(m.shape(),stride,ordering);
copyFromReal(m);
}
/** Construct a complex matrix from a realComponent matrix. */
public BaseComplexNDArray(INDArray m,char ordering) {
this(m.shape(),ordering);
copyFromReal(m);
}
/** Construct a complex matrix from a realComponent matrix. */
public BaseComplexNDArray(INDArray m) {
this(m, Nd4j.order());
}
/**
* Create with the specified ndarray as the real component
* and the given stride
* @param m the ndarray to use as the stride
* @param stride the stride of the ndarray
*/
public BaseComplexNDArray(INDArray m,int[] stride) {
this(m,stride, Nd4j.order());
}
/**
* Create an ndarray from the specified slices
* and the given shape
* @param slices the slices of the ndarray
* @param shape the final shape of the ndarray
* @param stride the stride of the ndarray
*/
public BaseComplexNDArray(List slices,int[] shape,int[] stride) {
this(slices,shape,stride, Nd4j.order());
}
/**
* Create an ndarray from the specified slices
* and the given shape
* @param slices the slices of the ndarray
* @param shape the final shape of the ndarray
* @param stride the stride of the ndarray
* @param ordering the ordering for the ndarray
*
*/
public BaseComplexNDArray(List slices,int[] shape,int[] stride,char ordering) {
this(new float[ArrayUtil.prod(shape) * 2]);
List list = new ArrayList<>();
for(int i = 0; i < slices.size(); i++) {
IComplexNDArray flattened = slices.get(i).ravel();
for(int j = 0; j < flattened.length(); j++)
list.add(flattened.getComplex(j));
}
this.ordering = ordering;
this.data = Nd4j.createBuffer(ArrayUtil.prod(shape) * 2);
this.stride = stride;
initShape(shape);
int count = 0;
for (int i = 0; i < list.size(); i++) {
putScalar(count,list.get(i));
count ++;
}
}
/**
* Create an ndarray from the specified slices
* and the given shape
* @param slices the slices of the ndarray
* @param shape the final shape of the ndarray
* @param ordering the ordering of the ndarray
*/
public BaseComplexNDArray(List slices,int[] shape,char ordering) {
this(slices,shape,ordering == NDArrayFactory.C ? ArrayUtil.calcStrides(shape,2) : ArrayUtil.calcStridesFortran(shape,2),ordering);
}
public BaseComplexNDArray(float[] data, int[] shape, int[] stride, int offset, Character order) {
this.data = Nd4j.createBuffer(data);
this.stride = stride;
this.offset = offset;
this.ordering = order;
initShape(shape);
}
public BaseComplexNDArray(DataBuffer data) {
super(data);
}
public BaseComplexNDArray(DataBuffer data, int[] shape, int[] stride, int offset) {
this.data = data;
this.stride = stride;
this.offset = offset;
this.ordering = Nd4j.order();
initShape(shape);
}
public BaseComplexNDArray(IComplexNumber[] data, int[] shape, int[] stride, int offset, char ordering) {
this(shape,stride,offset,ordering);
assert data.length <= length;
for(int i = 0; i < data.length; i++) {
putScalar(i, data[i]);
}
}
public BaseComplexNDArray(DataBuffer data, int[] shape) {
this(shape);
this.data = data;
}
public BaseComplexNDArray(IComplexNumber[] data, int[] shape, int[] stride, int offset) {
this(data,shape,stride,offset,Nd4j.order());
}
public BaseComplexNDArray(IComplexNumber[] data, int[] shape, int offset, char ordering) {
this(data,shape,Nd4j.getComplexStrides(shape),offset,ordering);
}
public BaseComplexNDArray(DataBuffer buffer, int[] shape, int offset, char ordering) {
this(buffer,shape,Nd4j.getComplexStrides(shape),offset,ordering);
}
public BaseComplexNDArray(DataBuffer buffer, int[] shape, int offset) {
this(buffer,shape,Nd4j.getComplexStrides(shape),offset,Nd4j.order());
}
public BaseComplexNDArray(float[] data, Character order) {
this(data,new int[]{data.length / 2},order);
}
protected void copyFromReal(INDArray real) {
INDArray linear = real.linearView();
IComplexNDArray thisLinear = linearView();
for(int i = 0; i < linear.length(); i++) {
thisLinear.putScalar(i, Nd4j.createComplexNumber(linear.getDouble(i),0));
}
}
protected void copyRealTo(INDArray arr) {
INDArray linear = arr.linearView();
IComplexNDArray thisLinear = linearView();
for(int i = 0; i < linear.length(); i++) {
arr.putScalar(i, thisLinear.getReal(i));
}
}
@Override
public int blasOffset() {
return offset > 0 ? offset() / 2 : offset();
}
@Override
public IComplexNDArray linearViewColumnOrder() {
return Nd4j.createComplex(data,new int[]{length,1},offset());
}
/**
* Returns a linear view reference of shape
* 1,length(ndarray)
*
* @return the linear view of this ndarray
*/
@Override
public IComplexNDArray linearView() {
if(isVector())
return this;
if(linearView == null)
linearView = Nd4j.createComplex(data, new int[]{1, length},stride(), offset());
return (IComplexNDArray) linearView;
}
/**
* Create an ndarray from the specified slices
* and the given shape
* @param slices the slices of the ndarray
* @param shape the final shape of the ndarray
*/
public BaseComplexNDArray(List slices,int[] shape) {
this(slices,shape, Nd4j.order());
}
/**
* Create a complex ndarray with the given complex doubles.
* Note that this maybe an easier setup than the new float
* @param newData the new data for this array
* @param shape the shape of the ndarray
*/
public BaseComplexNDArray(IComplexNumber[] newData,int[] shape) {
super(new float[ArrayUtil.prod(shape) * 2]);
initShape(shape);
for(int i = 0;i < length; i++)
put(i, newData[i].asDouble());
}
/**
* Create a complex ndarray with the given complex doubles.
* Note that this maybe an easier setup than the new float
* @param newData the new data for this array
* @param shape the shape of the ndarray
*/
public BaseComplexNDArray(IComplexNumber[] newData,int[] shape,int[] stride) {
super(new float[ArrayUtil.prod(shape) * 2]);
this.stride = stride;
initShape(shape);
for(int i = 0;i < length; i++)
put(i,newData[i].asDouble());
}
/**
* Create a complex ndarray with the given complex doubles.
* Note that this maybe an easier setup than the new float
* @param newData the new data for this array
* @param shape the shape of the ndarray
* @param ordering the ordering for the ndarray
*/
public BaseComplexNDArray(IComplexNumber[] newData,int[] shape,char ordering) {
super(new float[ArrayUtil.prod(shape) * 2]);
this.ordering = ordering;
initShape(shape);
for(int i = 0;i < length; i++)
put(i,newData[i]);
}
/**
* Initialize with the given data,shape and stride
* @param data the data to use
* @param shape the shape of the ndarray
* @param stride the stride of the ndarray
*/
public BaseComplexNDArray(float[] data,int[] shape,int[] stride) {
this(data,shape,stride,0, Nd4j.order());
}
public BaseComplexNDArray(float[] data,int[] shape) {
this(data,shape,0);
}
public BaseComplexNDArray(float[] data,int[] shape,int offset,char ordering) {
this(data,shape,ordering == NDArrayFactory.C ? calcStrides(shape,2) : calcStridesFortran(shape,2),offset,ordering);
}
public BaseComplexNDArray(float[] data,int[] shape,int offset) {
this(data,shape,offset, Nd4j.order());
}
/**
* Construct an ndarray of the specified shape
* with an empty data array
* @param shape the shape of the ndarray
* @param stride the stride of the ndarray
* @param offset the desired offset
*/
public BaseComplexNDArray(int[] shape,int[] stride,int offset) {
this(new float[ArrayUtil.prod(shape) * 2],shape,stride,offset);
}
/**
* Construct an ndarray of the specified shape
* with an empty data array
* @param shape the shape of the ndarray
* @param stride the stride of the ndarray
* @param offset the desired offset
* @param ordering the ordering for the ndarray
*/
public BaseComplexNDArray(int[] shape,int[] stride,int offset,char ordering) {
this(new float[ArrayUtil.prod(shape) * 2],shape,stride,offset);
this.ordering = ordering;
}
/**
* Create the ndarray with
* the specified shape and stride and an offset of 0
* @param shape the shape of the ndarray
* @param stride the stride of the ndarray
*/
public BaseComplexNDArray(int[] shape,int[] stride,char ordering){
this(shape,stride,0,ordering);
}
/**
* Create the ndarray with
* the specified shape and stride and an offset of 0
* @param shape the shape of the ndarray
* @param stride the stride of the ndarray
*/
public BaseComplexNDArray(int[] shape,int[] stride){
this(shape,stride,0);
}
/**
*
* @param shape
* @param offset
*/
public BaseComplexNDArray(int[] shape,int offset) {
this(shape,offset, Nd4j.order());
}
/**
* Creates a new n times mComplexDoubleMatrix.
*
* @param newRows the number of rows (n) of the new matrix.
* @param newColumns the number of columns (m) of the new matrix.
*/
public BaseComplexNDArray(int newRows, int newColumns) {
this(new int[]{newRows,newColumns});
}
/**
* Creates a new n times mComplexDoubleMatrix.
*
* @param newRows the number of rows (n) of the new matrix.
* @param newColumns the number of columns (m) of the new matrix.
* @param ordering the ordering of the ndarray
*/
public BaseComplexNDArray(int newRows, int newColumns,char ordering) {
this(new int[]{newRows,newColumns},ordering);
}
public BaseComplexNDArray(float[] data, int[] shape, int[] stride, int offset) {
this(data,shape,stride,offset, Nd4j.order());
}
@Override
public IComplexNumber getComplex(int i, IComplexNumber result) {
IComplexNumber d = getComplex(i);
return result.set(d.realComponent(),d.imaginaryComponent());
}
@Override
public IComplexNumber getComplex(int i, int j, IComplexNumber result) {
IComplexNumber d = getComplex(i,j);
return result.set(d.realComponent(),d.imaginaryComponent());
}
@Override
public IComplexNDArray putScalar(int j, int i, IComplexNumber conji) {
int idx = index(j,i);
data.put(idx, conji.realComponent().doubleValue());
data.put(idx + 1,conji.imaginaryComponent().doubleValue());
return this;
}
/**
* Returns an ndarray with 1 if the element is epsilon equals
*
* @param other the number to compare
* @return a copied ndarray with the given
* binary conditions
*/
@Override
public IComplexNDArray eps(Number other) {
return dup().epsi(other);
}
/**
* Returns an ndarray with 1 if the element is epsilon equals
*
* @param other the number to compare
* @return a copied ndarray with the given
* binary conditions
*/
@Override
public IComplexNDArray eps(IComplexNumber other) {
return dup().epsi(other);
}
/**
* Returns an ndarray with 1 if the element is epsilon equals
*
* @param other the number to compare
* @return a copied ndarray with the given
* binary conditions
*/
@Override
public IComplexNDArray epsi(IComplexNumber other) {
IComplexNDArray linear = linearView();
float otherVal = other.realComponent().floatValue();
for(int i = 0; i < linearView().length(); i++) {
IComplexNumber n = linear.getComplex(i);
float real = n.realComponent().floatValue();
float diff = Math.abs(real - otherVal);
if(diff <= Nd4j.EPS_THRESHOLD)
linear.putScalar(i,Nd4j.createDouble(1,0));
else
linear.putScalar(i,Nd4j.createDouble(0,0));
}
return this;
}
/**
* Returns an ndarray with 1 if the element is epsilon equals
*
* @param other the number to compare
* @return a copied ndarray with the given
* binary conditions
*/
@Override
public IComplexNDArray epsi(Number other) {
IComplexNDArray linear = linearView();
float otherVal = other.floatValue();
for(int i = 0; i < linearView().length(); i++) {
IComplexNumber n = linear.getComplex(i);
float real = n.realComponent().floatValue();
float diff = Math.abs(real - otherVal);
if(diff <= Nd4j.EPS_THRESHOLD)
linear.putScalar(i,Nd4j.createDouble(1,0));
else
linear.putScalar(i,Nd4j.createDouble(0,0));
}
return this;
}
/**
* epsilon equals than comparison:
* If the given number is less than the
* comparison number the item is 0 otherwise 1
*
* @param other the number to compare
* @return
*/
@Override
public IComplexNDArray eps(INDArray other) {
return dup().epsi(other);
}
/**
* In place epsilon equals than comparison:
* If the given number is less than the
* comparison number the item is 0 otherwise 1
*
* @param other the number to compare
* @return
*/
@Override
public IComplexNDArray epsi(INDArray other) {
IComplexNDArray linear = linearView();
if(other instanceof IComplexNDArray) {
IComplexNDArray otherComplex = (IComplexNDArray) other;
IComplexNDArray otherComplexLinear = otherComplex.linearView();
for(int i = 0; i < linearView().length(); i++) {
IComplexNumber n = linear.getComplex(i);
IComplexNumber otherComplexNumber = otherComplexLinear.getComplex(i);
float real = n.absoluteValue().floatValue();
float otherAbs = otherComplexNumber.absoluteValue().floatValue();
float diff = Math.abs(real - otherAbs);
if(diff <= Nd4j.EPS_THRESHOLD)
linear.putScalar(i,Nd4j.createDouble(1,0));
else
linear.putScalar(i,Nd4j.createDouble(0,0));
}
}
return this;
}
@Override
public IComplexNDArray lt(Number other) {
return dup().lti(other);
}
@Override
public IComplexNDArray lti(Number other) {
IComplexNDArray linear = linearView();
float val = other.floatValue();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue() < val ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
return this;
}
@Override
public IComplexNDArray eq(Number other) {
return dup().eqi(other);
}
@Override
public IComplexNDArray eqi(Number other) {
IComplexNDArray linear = linearView();
float val = other.floatValue();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue() == val ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
return this;
}
@Override
public IComplexNDArray gt(Number other) {
return dup().gti(other);
}
@Override
public IComplexNDArray gti(Number other) {
IComplexNDArray linear = linearView();
float val = other.floatValue();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue() > val ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
return this;
}
@Override
public IComplexNDArray lt(INDArray other) {
return dup().lti(other);
}
@Override
public IComplexNDArray lti(INDArray other) {
if(other instanceof IComplexNDArray) {
IComplexNDArray linear = linearView();
IComplexNDArray otherLinear = (IComplexNDArray) other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
< otherLinear.getComplex(i).absoluteValue().floatValue() ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
else {
IComplexNDArray linear = linearView();
INDArray otherLinear = other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
< otherLinear.getDouble(i) ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
return this;
}
@Override
public IComplexNDArray eq(INDArray other) {
return dup().eqi(other);
}
@Override
public IComplexNDArray eqi(INDArray other) {
if(other instanceof IComplexNDArray) {
IComplexNDArray linear = linearView();
IComplexNDArray otherLinear = (IComplexNDArray) other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
== otherLinear.getComplex(i).absoluteValue().floatValue() ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
else {
IComplexNDArray linear = linearView();
INDArray otherLinear = other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
== otherLinear.getDouble(i) ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
return this;
}
@Override
public IComplexNDArray neq(INDArray other) {
return dup().neqi(other);
}
@Override
public IComplexNDArray neqi(INDArray other) {
if(other instanceof IComplexNDArray) {
IComplexNDArray linear = linearView();
IComplexNDArray otherLinear = (IComplexNDArray) other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
!= otherLinear.getComplex(i).absoluteValue().floatValue() ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
else {
IComplexNDArray linear = linearView();
INDArray otherLinear = other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
!= otherLinear.getDouble(i) ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
return this;
}
@Override
public IComplexNDArray gt(INDArray other) {
return dup().gti(other);
}
@Override
public IComplexNDArray gti(INDArray other) {
if(other instanceof IComplexNDArray) {
IComplexNDArray linear = linearView();
IComplexNDArray otherLinear = (IComplexNDArray) other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
> otherLinear.getComplex(i).absoluteValue().floatValue() ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
else {
IComplexNDArray linear = linearView();
INDArray otherLinear = other.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,linear.getComplex(i).absoluteValue().floatValue()
> otherLinear.getDouble(i) ? Nd4j.createComplexNumber(1,0) : Nd4j.createComplexNumber(0,0));
}
}
return this;
}
@Override
public IComplexNDArray rdiv(Number n, INDArray result) {
return dup().rdivi(n,result);
}
@Override
public IComplexNDArray rdivi(Number n, INDArray result) {
return rdivi(Nd4j.createFloat(n.floatValue(), 0), result);
}
@Override
public IComplexNDArray rsub(Number n, INDArray result) {
return dup().rsubi(n,result);
}
@Override
public IComplexNDArray rsubi(Number n, INDArray result) {
return rsubi(Nd4j.createFloat(n.floatValue(), 0), result);
}
@Override
public IComplexNDArray div(Number n, INDArray result) {
return dup().divi(n,result);
}
@Override
public IComplexNDArray divi(Number n, INDArray result) {
return divi(Nd4j.createFloat(n.floatValue(), 0), result);
}
@Override
public IComplexNDArray mul(Number n, INDArray result) {
return dup().muli(n,result);
}
@Override
public IComplexNDArray muli(Number n, INDArray result) {
return muli(Nd4j.createFloat(n.floatValue(), 0), result);
}
@Override
public IComplexNDArray sub(Number n, INDArray result) {
return dup().subi(n,result);
}
@Override
public IComplexNDArray subi(Number n, INDArray result) {
return subi(Nd4j.createDouble(n.doubleValue(), 0), result);
}
@Override
public IComplexNDArray add(Number n, INDArray result) {
return dup().addi(n,result);
}
@Override
public IComplexNDArray addi(Number n, INDArray result) {
return addi(Nd4j.createFloat(n.floatValue(), 0),result);
}
@Override
public IComplexNDArray dup() {
IComplexNDArray ret = Nd4j.createComplex(shape());
IComplexNDArray linear = linearView();
IComplexNDArray retLinear = ret.linearView();
for(int i = 0; i < ret.length(); i++) {
retLinear.putScalar(i,linear.getComplex(i));
}
return ret;
}
@Override
public IComplexNDArray rsubRowVector(INDArray rowVector) {
return dup().rsubiRowVector(rowVector);
}
@Override
public IComplexNDArray rsubiRowVector(INDArray rowVector) {
return doRowWise(rowVector, 't');
}
@Override
public IComplexNDArray rsubColumnVector(INDArray columnVector) {
return dup().rsubiColumnVector(columnVector);
}
@Override
public IComplexNDArray rsubiColumnVector(INDArray columnVector) {
return doColumnWise(columnVector, 'h');
}
@Override
public IComplexNDArray rdivRowVector(INDArray rowVector) {
return dup().rdiviRowVector(rowVector);
}
@Override
public IComplexNDArray rdiviRowVector(INDArray rowVector) {
return doRowWise(rowVector, 't');
}
@Override
public IComplexNDArray rdivColumnVector(INDArray columnVector) {
return dup().rdiviColumnVector(columnVector);
}
@Override
public IComplexNDArray rdiviColumnVector(INDArray columnVector) {
return doColumnWise(columnVector,'t');
}
@Override
protected IComplexNDArray doRowWise(INDArray rowVector, char operation) {
assertRowVector(rowVector);
for(int i = 0; i < rows(); i++) {
switch(operation) {
case 'a' : getRow(i).addi(rowVector); break;
case 's' : getRow(i).subi(rowVector); break;
case 'm' : getRow(i).muli(rowVector); break;
case 'd' : getRow(i).divi(rowVector); break;
case 'h' : getRow(i).rsubi(rowVector); break;
case 't' : getRow(i).rdivi(rowVector); break;
}
}
return this;
}
@Override
protected IComplexNDArray doColumnWise(INDArray columnVector, char operation) {
asserColumnVector(columnVector);
for(int i = 0; i < columns(); i++) {
IComplexNDArray slice = slice(i,0);
switch(operation) {
case 'a' : slice.addi(columnVector); break;
case 's' : slice.subi(columnVector); break;
case 'm' : slice.muli(columnVector); break;
case 'd' : slice.divi(columnVector); break;
case 'h' : slice.rsubi(columnVector); break;
case 't' : slice.rdivi(columnVector); break;
}
}
return this;
}
/**
* Returns the squared (Euclidean) distance.
*/
@Override
public double squaredDistance(INDArray other) {
double sd = 0.0;
if(other instanceof IComplexNDArray) {
IComplexNDArray n = (IComplexNDArray) other;
IComplexNDArray nLinear = n.linearView();
for (int i = 0; i < length; i++) {
IComplexNumber diff = linearView().getComplex(i).sub(nLinear.getComplex(i));
double d = diff.absoluteValue().doubleValue();
sd += d * d;
}
return sd;
}
for (int i = 0; i < length; i++) {
INDArray linear = other.linearView();
IComplexNumber diff = linearView().getComplex(i).sub(linear.getDouble(i));
double d = diff.absoluteValue().doubleValue();
sd += d * d;
}
return sd;
}
/**
* Returns the (euclidean) distance.
*/
@Override
public double distance2(INDArray other) {
return Math.sqrt(squaredDistance(other));
}
/**
* Returns the (1-norm) distance.
*/
@Override
public double distance1(INDArray other) {
float d = 0.0f;
if(other instanceof IComplexNDArray) {
IComplexNDArray n2 = (IComplexNDArray) other;
IComplexNDArray n2Linear = n2.linearView();
for (int i = 0; i < length; i++) {
IComplexNumber n = getComplex(i).sub(n2Linear.getComplex(i));
d += n.absoluteValue().doubleValue();
}
return d;
}
INDArray linear = other.linearView();
for (int i = 0; i < length; i++) {
IComplexNumber n = linearView().getComplex(i).sub(linear.getDouble(i));
d += n.absoluteValue().doubleValue();
}
return d;
}
@Override
public IComplexNDArray put(NDArrayIndex[] indices, INDArray element) {
if(Indices.isContiguous(indices)) {
IComplexNDArray get = get(indices);
IComplexNDArray linear = get.linearView();
IComplexNDArray imag = element instanceof IComplexNDArray ? (IComplexNDArray) element : Nd4j.createComplex(element);
IComplexNDArray elementLinear = imag.linearView();
if(element.isScalar()) {
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,elementLinear.getComplex(0));
}
}
if(Shape.shapeEquals(element.shape(),get.shape()) || element.length() <= get.length()) {
for(int i = 0; i < elementLinear.length(); i++) {
linear.putScalar(i,elementLinear.getComplex(i));
}
}
}
else {
if(isVector()) {
assert indices.length == 1 : "Indices must only be of length 1.";
assert element.isScalar() || element.isVector() : "Unable to assign elements. Element is not a vector.";
assert indices[0].length() == element.length() : "Number of specified elements in index does not match length of element.";
int[] assign = indices[0].indices();
IComplexNDArray imag = element instanceof IComplexNDArray ? (IComplexNDArray) element : Nd4j.createComplex(element);
IComplexNDArray elementLinear = imag.linearView();
for(int i = 0; i < element.length(); i++) {
putScalar(assign[i],elementLinear.getComplex(i));
}
return this;
}
if(element.isVector())
slice(indices[0].indices()[0]).put(Arrays.copyOfRange(indices,1,indices.length),element);
else {
for(int i = 0; i < element.slices(); i++) {
INDArray slice = slice(indices[0].indices()[i]);
slice.put(Arrays.copyOfRange(indices,1,indices.length),element.slice(i));
}
}
}
return this;
}
@Override
public IComplexNDArray normmax(int dimension) {
return Nd4j.createComplex(super.normmax(dimension));
}
@Override
public IComplexNDArray prod(int dimension) {
return Nd4j.createComplex(super.prod(dimension));
}
@Override
public IComplexNDArray mean(int dimension) {
return Nd4j.createComplex(super.mean(dimension));
}
@Override
public IComplexNDArray var(int dimension) {
return Nd4j.createComplex(super.var(dimension));
}
@Override
public IComplexNDArray max(int dimension) {
return Nd4j.createComplex(super.max(dimension));
}
@Override
public IComplexNDArray sum(int dimension) {
return Nd4j.createComplex(super.sum(dimension));
}
@Override
public IComplexNDArray min(int dimension) {
return Nd4j.createComplex(super.min(dimension));
}
@Override
public IComplexNDArray norm1(int dimension) {
return Nd4j.createComplex(super.norm1(dimension));
}
@Override
public IComplexNDArray std(int dimension) {
return Nd4j.createComplex(super.std(dimension));
}
@Override
public IComplexNDArray norm2(int dimension) {
return Nd4j.createComplex(super.norm2(dimension));
}
/**
* Inserts the element at the specified index
*
* @param i the row insert into
* @param j the column to insert into
* @param element a scalar ndarray
* @return a scalar ndarray of the element at this index
*/
@Override
public IComplexNDArray put(int i, int j, Number element) {
return put(i,j, Nd4j.scalar(element));
}
/**
* @param indexes
* @param value
* @return
*/
@Override
public IComplexNDArray put(int[] indexes, float value) {
int ix = offset;
if (indexes.length != shape.length)
throw new IllegalArgumentException("Unable to applyTransformToDestination values: number of indices must be equal to the shape");
for (int i = 0; i< shape.length; i++)
ix += indexes[i] * stride[i];
data.put(ix,value);
return this;
}
/**
* Assigns the given matrix (put) to the specified slice
* @param slice the slice to assign
* @param put the slice to applyTransformToDestination
* @return this for chainability
*/
@Override
public IComplexNDArray putSlice(int slice, IComplexNDArray put) {
if(isScalar()) {
assert put.isScalar() : "Invalid dimension. Can only insert a scalar in to another scalar";
putScalar(0, put.getDouble(0));
return this;
}
else if(isVector()) {
assert put.isScalar() : "Invalid dimension on insertion. Can only insert scalars input vectors";
putScalar(slice, put.getDouble(0));
return this;
}
assertSlice(put,slice);
IComplexNDArray view = slice(slice);
if(put.isScalar())
putScalar(slice, put.getDouble(0));
else if(put.isVector())
for(int i = 0; i < put.length(); i++)
view.putScalar(i, put.getComplex(i));
else if(put.shape().length == 2)
for(int i = 0; i < put.rows(); i++)
for(int j = 0; j < put.columns(); j++)
view.put(i,j,put.getDouble(i, j));
else {
assert put.slices() == view.slices() : "Slices must be equivalent.";
for(int i = 0; i < put.slices(); i++)
view.slice(i).putSlice(i,view.slice(i));
}
return this;
}
/**
* Mainly here for people coming from numpy.
* This is equivalent to a call to permute
* @param dimension the dimension to swap
* @param with the one to swap it with
* @return the swapped axes view
*/
public IComplexNDArray swapAxes(int dimension,int with) {
int[] shape = ArrayUtil.range(0,shape().length);
shape[dimension] = with;
shape[with] = dimension;
return permute(shape);
}
/**
* Compute complex conj (in-place).
*/
@Override
public IComplexNDArray conji() {
IComplexNDArray reshaped = linearView();
IComplexDouble c = Nd4j.createDouble(0.0, 0);
for (int i = 0; i < length; i++) {
IComplexNumber conj = reshaped.getComplex(i, c).conj();
reshaped.putScalar(i, conj);
}
return this;
}
@Override
public IComplexNDArray hermitian() {
IComplexNDArray result = Nd4j.createComplex(shape());
IComplexDouble c = Nd4j.createDouble(0, 0);
for (int i = 0; i < slices(); i++)
for (int j = 0; j < columns; j++)
result.putScalar(j, i, getComplex(i, j, c).conji());
return result;
}
/**
* Compute complex conj.
*/
@Override
public IComplexNDArray conj() {
return dup().conji();
}
@Override
public INDArray getReal() {
INDArray result = Nd4j.create(shape());
IComplexNDArray linearView = linearView();
INDArray linearRet = result.linearView();
for(int i = 0; i < linearView.length(); i++) {
linearRet.putScalar(i,linearView.getReal(i));
}
return result;
}
@Override
public double getImag(int i) {
int linear = linearIndex(i);
return data.getDouble(linear + 1);
}
@Override
public double getReal(int i) {
int linear = linearIndex(i);
return data.getDouble(linear);
}
@Override
public IComplexNDArray putReal(int rowIndex, int columnIndex, float value) {
data.put(2 * index(rowIndex, columnIndex) + offset,value);
return this;
}
@Override
public int linearIndex(int i) {
int realStride = majorStride();
int idx = offset + (i * realStride);
if(idx >= data.length())
throw new IllegalArgumentException("Illegal index " + idx + " derived from " + i + " with offset of " + offset + " and stride of " + realStride);
return idx;
}
@Override
public IComplexNDArray putImag(int rowIndex, int columnIndex, float value) {
data.put(index(rowIndex, columnIndex) + 1 + offset,value);
return this;
}
@Override
public IComplexNDArray putReal(int i, float v) {
int idx = linearIndex(i);
data.put(idx,v);
return this;
}
@Override
public IComplexNDArray putImag(int i, float v) {
int idx = linearIndex(i);
data.put(idx * 2 + 1,v);
return this;
}
@Override
public IComplexNumber getComplex(int i) {
int idx = linearIndex(i);
return Nd4j.createDouble(data.getDouble(idx), data.getDouble(idx + 1));
}
@Override
public IComplexNumber getComplex(int i, int j) {
int idx = index(i,j);
return Nd4j.createDouble(data.getDouble(idx), data.getDouble(idx + 1));
}
/**
* Get realComponent part of the matrix.
*/
@Override
public INDArray real() {
INDArray ret = Nd4j.create(shape);
copyRealTo(ret);
return ret;
}
/**
* Get imaginary part of the matrix.
*/
@Override
public INDArray imag() {
INDArray ret = Nd4j.create(shape);
Nd4j.getBlasWrapper().dcopy(length, data.asFloat(), 1, 2, ret.data().asFloat(), 0, 1);
return ret;
}
/**
* Iterate along a dimension.
* This encapsulates the process of sum, mean, and other processes
* take when iterating over a dimension.
* @param dimension the dimension to iterate over
* @param op the operation to apply
* @param modify whether to modify this array or not based on the results
*/
@Override
public void iterateOverDimension(int dimension,SliceOp op,boolean modify) {
if(isScalar()) {
if(dimension > 1)
throw new IllegalArgumentException("Dimension must be 0 for a scalar");
else {
DimensionSlice slice = this.vectorForDimensionAndOffset(0,0);
op.operate(slice);
if(modify && slice.getIndices() != null) {
IComplexNDArray result = (IComplexNDArray) slice.getResult();
for(int i = 0; i < slice.getIndices().length; i++) {
data.put(slice.getIndices()[i],result.getComplex(i).realComponent().doubleValue());
data.put(slice.getIndices()[i] + 1, result.getComplex(i).imaginaryComponent().doubleValue());
}
}
}
}
else if(isVector()) {
if(dimension == 0) {
DimensionSlice slice = vectorForDimensionAndOffset(0,0);
op.operate(slice);
if(modify && slice.getIndices() != null) {
IComplexNDArray result = (IComplexNDArray) slice.getResult();
for(int i = 0; i < slice.getIndices().length; i++) {
data.put(slice.getIndices()[i] ,result.getComplex(i).realComponent().doubleValue());
data.put(slice.getIndices()[i] + 1, result.getComplex(i).imaginaryComponent().doubleValue());
}
}
}
else if(dimension == 1) {
for(int i = 0; i < length; i++) {
DimensionSlice slice = vectorForDimensionAndOffset(dimension,i);
op.operate(slice);
if(modify && slice.getIndices() != null) {
IComplexNDArray result = (IComplexNDArray) slice.getResult();
for(int j = 0; j < slice.getIndices().length; j++) {
data.put(slice.getIndices()[j],result.getComplex(j).realComponent().doubleValue());
data.put(slice.getIndices()[j] + 1,result.getComplex(j).imaginaryComponent().doubleValue());
}
}
}
}
else
throw new IllegalArgumentException("Illegal dimension for vector " + dimension);
}
else {
if(dimension >= shape.length)
throw new IllegalArgumentException("Unable to remove dimension " + dimension + " was >= shape length");
int[] shape = ArrayUtil.removeIndex(this.shape,dimension);
if(dimension == 0) {
//iterating along the dimension is relative to the number of slices
//in the return dimension
int numTimes = ArrayUtil.prod(shape);
//note difference here from ndarray, the offset is incremented by 2 every time
//note also numtimes is multiplied by 2, this is due to the complex and imaginary components
for(int offset = this.offset; offset < numTimes ; offset += 2) {
DimensionSlice vector = vectorForDimensionAndOffset(dimension,offset);
op.operate(vector);
if(modify && vector.getIndices() != null) {
IComplexNDArray result = (IComplexNDArray) vector.getResult();
for(int i = 0; i < vector.getIndices().length; i++) {
data.put(vector.getIndices()[i],result.getComplex(i).realComponent().doubleValue());
data.put(vector.getIndices()[i] + 1,result.getComplex(i).imaginaryComponent().doubleValue());
}
}
}
}
else {
//needs to be 2 * shape: this is due to both realComponent and imaginary components
float[] data2 = new float[ArrayUtil.prod(shape) ];
int dataIter = 0;
//want the milestone to slice[1] and beyond
int[] sliceIndices = endsForSlices();
int currOffset = 0;
//iterating along the dimension is relative to the number of slices
//in the return dimension
//note here the and +=2 this is for iterating over realComponent and imaginary components
for(int offset = this.offset;;) {
if(dataIter >= data2.length || currOffset >= sliceIndices.length)
break;
//do the operation,, and look for whether it exceeded the current slice
DimensionSlice pair = vectorForDimensionAndOffsetPair(dimension, offset,sliceIndices[currOffset]);
//append the result
op.operate(pair);
if(modify && pair.getIndices() != null) {
IComplexNDArray result = (IComplexNDArray) pair.getResult();
for(int i = 0; i < pair.getIndices().length; i++) {
data.put(pair.getIndices()[i],result.getComplex(i).realComponent().doubleValue());
data.put(pair.getIndices()[i] + 1,result.getComplex(i).imaginaryComponent().doubleValue());
}
}
//go to next slice and iterate over that
if(pair.isNextSlice()) {
//DO NOT CHANGE
currOffset++;
if(currOffset >= sliceIndices.length)
break;
//will update to next step
offset = sliceIndices[currOffset];
}
}
}
}
}
//getFromOrigin one result along one dimension based on the given offset
public DimensionSlice vectorForDimensionAndOffsetPair(int dimension, int offset,int currOffsetForSlice) {
int count = 0;
IComplexNDArray ret = Nd4j.createComplex(new int[]{shape[dimension]});
boolean newSlice = false;
List indices = new ArrayList<>();
for(int j = offset; count < this.shape[dimension]; j+= this.stride[dimension] ) {
IComplexDouble d = Nd4j.createDouble(data.getDouble(j), data.getDouble(j + 1));
indices.add(j);
ret.putScalar(count++, d);
if(j >= currOffsetForSlice)
newSlice = true;
}
return new DimensionSlice(newSlice,ret,ArrayUtil.toArray(indices));
}
//getFromOrigin one result along one dimension based on the given offset
public DimensionSlice vectorForDimensionAndOffset(int dimension, int offset) {
if(isScalar() && dimension == 0 && offset == 0)
return new DimensionSlice(false, Nd4j.complexScalar(getDouble(offset)),new int[]{offset});
//need whole vector
else if (isVector()) {
if(dimension == 0) {
int[] indices = new int[length];
for(int i = 0; i < indices.length; i++)
indices[i] = i;
return new DimensionSlice(false,dup(),indices);
}
else if(dimension == 1) {
return new DimensionSlice(false, Nd4j.complexScalar(getDouble(offset)),new int[]{offset});
}
else
throw new IllegalArgumentException("Illegal dimension for vector " + dimension);
}
else {
int count = 0;
IComplexNDArray ret = Nd4j.createComplex(new int[]{shape[dimension]});
List indices = new ArrayList<>();
for (int j = offset; count < this.shape[dimension]; j += this.stride[dimension] ) {
IComplexDouble d = Nd4j.createDouble(data.getDouble(j), data.getDouble(j + 1));
ret.putScalar(count++, d);
indices.add(j);
}
return new DimensionSlice(false, ret, ArrayUtil.toArray(indices));
}
}
/**
* Inserts the element at the specified index
*
* @param i the index insert into
* @param element a scalar ndarray
* @return a scalar ndarray of the element at this index
*/
@Override
public IComplexNDArray put(int i, IComplexNDArray element) {
if(element == null)
throw new IllegalArgumentException("Unable to insert null element");
assert element.isScalar() : "Unable to insert non scalar element";
int idx = linearIndex(i);
IComplexNumber n = element.getComplex(0);
data.put(idx, n.realComponent().doubleValue());
data.put(idx + 1, n.imaginaryComponent().doubleValue());
return this;
}
//getFromOrigin one result along one dimension based on the given offset
private ComplexIterationResult op(int dimension, int offset, Ops.DimensionOp op,int currOffsetForSlice) {
double[] dim = new double[this.shape[dimension]];
int count = 0;
boolean newSlice = false;
for(int j = offset; count < dim.length; j+= this.stride[dimension]) {
double d = data.getDouble(j);
dim[count++] = d;
if(j >= currOffsetForSlice)
newSlice = true;
}
IComplexNDArray r = Nd4j.createComplex(dim);
IComplexDouble r2 = reduceVector(op,r);
return new ComplexIterationResult(newSlice,r2);
}
//getFromOrigin one result along one dimension based on the given offset
private IComplexNumber op(int dimension, int offset, Ops.DimensionOp op) {
double[] dim = new double[this.shape[dimension]];
int count = 0;
for(int j = offset; count < dim.length; j+= this.stride[dimension]) {
double d = data.getDouble(j);
dim[count++] = d;
}
return reduceVector(op, Nd4j.createComplex(dim));
}
private IComplexDouble reduceVector(Ops.DimensionOp op,IComplexNDArray vector) {
switch(op) {
case SUM:
return (IComplexDouble) vector.sum(Integer.MAX_VALUE).element();
case MEAN:
return (IComplexDouble) vector.mean(Integer.MAX_VALUE).element();
case NORM_1:
return Nd4j.createDouble((double) vector.norm1(Integer.MAX_VALUE).element(), 0);
case NORM_2:
return Nd4j.createDouble((double) vector.norm2(Integer.MAX_VALUE).element(), 0);
case NORM_MAX:
return Nd4j.createDouble((double) vector.normmax(Integer.MAX_VALUE).element(), 0);
case FFT:
default: throw new IllegalArgumentException("Illegal operation");
}
}
/**
* Fetch a particular number on a multi dimensional scale.
*
* @param indexes the indexes to getFromOrigin a number from
* @return the number at the specified indices
*/
@Override
public IComplexNDArray getScalar(int... indexes) {
int ix = offset;
for (int i = 0; i < shape.length; i++) {
ix += indexes[i] * stride[i];
}
return Nd4j.scalar(Nd4j.createDouble(data.getDouble(ix), data.getDouble(ix + 1)));
}
/**
* Validate dimensions are equal
*
* @param other the other ndarray to compare
*/
@Override
public void checkDimensions(INDArray other) {
}
/**
* Gives the indices for the ending of each slice
* @return the off sets for the beginning of each slice
*/
@Override
public int[] endsForSlices() {
int[] ret = new int[slices()];
int currOffset = offset;
for(int i = 0; i < slices(); i++) {
ret[i] = (currOffset );
currOffset += stride[0];
}
return ret;
}
/**
* http://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.reduce.html
*
* @param op the operation to do
* @param dimension the dimension to return from
* @return the results of the reduce (applying the operation along the specified
* dimension)t
*/
@Override
public IComplexNDArray reduce(Ops.DimensionOp op, int dimension) {
if(isScalar())
return this;
if(isVector())
return Nd4j.scalar(reduceVector(op, this));
int[] shape = ArrayUtil.removeIndex(this.shape,dimension);
if(dimension == 0) {
float[] data2 = new float[ArrayUtil.prod(shape) * 2];
int dataIter = 0;
//iterating along the dimension is relative to the number of slices
//in the return dimension
int numTimes = ArrayUtil.prod(shape);
for(int offset = this.offset; offset < numTimes; offset++) {
IComplexNumber reduce = op(dimension, offset, op);
data2[dataIter++] = reduce.realComponent().floatValue();
data2[dataIter++] = reduce.imaginaryComponent().floatValue();
}
return Nd4j.createComplex(data2, shape);
}
else {
float[] data2 = new float[ArrayUtil.prod(shape)];
int dataIter = 0;
//want the milestone to slice[1] and beyond
int[] sliceIndices = endsForSlices();
int currOffset = 0;
//iterating along the dimension is relative to the number of slices
//in the return dimension
int numTimes = ArrayUtil.prod(shape);
for(int offset = this.offset; offset < numTimes; offset++) {
if(dataIter >= data2.length || currOffset >= sliceIndices.length)
break;
//do the operation,, and look for whether it exceeded the current slice
ComplexIterationResult pair = op(dimension, offset, op,sliceIndices[currOffset]);
//append the result
IComplexNumber reduce = pair.getNumber();
data2[dataIter++] = reduce.realComponent().floatValue();
data2[dataIter++] = reduce.imaginaryComponent().floatValue();
//go to next slice and iterate over that
if(pair.isNextIteration()) {
//will update to next step
offset = sliceIndices[currOffset];
numTimes += sliceIndices[currOffset];
currOffset++;
}
}
return Nd4j.createComplex(data2, shape);
}
}
/**
* Assigns the given matrix (put) to the specified slice
*
* @param slice the slice to assign
* @param put the slice to put
* @return this for chainability
*/
@Override
public IComplexNDArray putSlice(int slice, INDArray put) {
if(isScalar()) {
assert put.isScalar() : "Invalid dimension. Can only insert a scalar in to another scalar";
put(0,put.getScalar(0));
return this;
}
else if(isVector()) {
assert put.isScalar() : "Invalid dimension on insertion. Can only insert scalars input vectors";
put(slice,put.getScalar(0));
return this;
}
assertSlice(put,slice);
IComplexNDArray view = slice(slice);
if(put.isScalar())
put(slice,put.getScalar(0));
else if(put.isVector())
for(int i = 0; i < put.length(); i++)
view.put(i,put.getScalar(i));
else if(put.shape().length == 2) {
if(put instanceof IComplexNDArray) {
IComplexNDArray complexPut = (IComplexNDArray) put;
for(int i = 0; i < put.rows(); i++)
for(int j = 0; j < put.columns(); j++)
view.putScalar(i,j,complexPut.getComplex(i, j));
}
for(int i = 0; i < put.rows(); i++)
for(int j = 0; j < put.columns(); j++)
view.putScalar(i,j,Nd4j.createDouble(put.getDouble(i, j),0.0));
}
else {
assert put.slices() == view.slices() : "Slices must be equivalent.";
for(int i = 0; i < put.slices(); i++)
view.slice(i).putSlice(i,view.slice(i));
}
return this;
}
@Override
public IComplexNDArray subArray(int[] offsets, int[] shape,int[] stride) {
int n = shape.length;
if (offsets.length != n)
throw new IllegalArgumentException("Invalid offset " + Arrays.toString(offsets));
if (shape.length != n)
throw new IllegalArgumentException("Invalid shape " + Arrays.toString(shape));
if (Arrays.equals(shape, this.shape)) {
if (ArrayUtil.isZero(offsets)) {
return this;
} else {
throw new IllegalArgumentException("Invalid subArray offsets");
}
}
return Nd4j.createComplex(
data
, Arrays.copyOf(shape, shape.length)
, stride
, offset + ArrayUtil.dotProduct(offsets, stride)
);
}
@Override
public int majorStride() {
if(offset == 0)
return super.majorStride();
else {
//stride already taken in to account once by offset
return super.majorStride();
}
}
/**
* Inserts the element at the specified index
*
* @param indices the indices to insert into
* @param element a scalar ndarray
* @return a scalar ndarray of the element at this index
*/
@Override
public IComplexNDArray put(int[] indices, INDArray element) {
if(!element.isScalar())
throw new IllegalArgumentException("Unable to insert anything but a scalar");
int ix = offset;
if (indices.length != shape.length)
throw new IllegalArgumentException("Unable to transform values: number of indices must be equal to the shape");
for (int i = 0; i< shape.length; i++)
ix += indices[i] * stride[i];
if(element instanceof IComplexNDArray) {
IComplexNumber element2 = ((IComplexNDArray) element).getComplex(0);
data.put(ix, element2.realComponent().doubleValue());
data.put(ix + 1,element2.imaginaryComponent().doubleValue());
}
else {
double element2 = (double) element.element();
data.put(ix,element2);
data.put(ix + 1,0);
}
return this;
}
/**
* Inserts the element at the specified index
*
* @param i the row insert into
* @param j the column to insert into
* @param element a scalar ndarray
* @return a scalar ndarray of the element at this index
*/
@Override
public IComplexNDArray put(int i, int j, INDArray element) {
return put(new int[]{i,j},element);
}
/**
* Returns the specified slice of this matrix.
* In matlab, this would be equivalent to (given a 2 x 2 x 2):
* A(:,:,x) where x is the slice you want to return.
*
* The slice is always relative to the final dimension of the matrix.
*
* @param slice the slice to return
* @return the specified slice of this matrix
*/
@Override
public IComplexNDArray slice(int slice) {
int offset = this.offset + (slice * majorStride());
IComplexNDArray ret;
if (shape.length == 0)
throw new IllegalArgumentException("Can't slice a 0-d ComplexNDArray");
//slice of a vector is a scalar
else if (shape.length == 1)
ret = Nd4j.createComplex(
data,
ArrayUtil.empty(),
ArrayUtil.empty(),
offset, ordering);
//slice of a matrix is a vector
else if (shape.length == 2) {
ret = Nd4j.createComplex(
data,
ArrayUtil.of(shape[1]),
Arrays.copyOfRange(stride, 1, stride.length),
offset, ordering
);
}
else {
if(offset >= data.length())
throw new IllegalArgumentException("Offset index is > data.length");
ret = Nd4j.createComplex(data,
Arrays.copyOfRange(shape, 1, shape.length),
Arrays.copyOfRange(stride,1,stride.length),
offset, ordering);
}
return ret;
}
/**
* Returns the slice of this from the specified dimension
* @param slice the dimension to return from
* @param dimension the dimension of the slice to return
* @return the slice of this matrix from the specified dimension
* and dimension
*/
@Override
public IComplexNDArray slice(int slice, int dimension) {
int offset = this.offset + dimension * stride[slice];
if(this.offset == 0)
offset *= 2;
IComplexNDArray ret;
if (shape.length == 2) {
int st = stride[1];
if (st == 1) {
return Nd4j.createComplex(
data,
new int[]{shape[dimension]},
offset, ordering);
} else {
return Nd4j.createComplex(
data,
new int[]{shape[dimension]},
new int[]{st},
offset);
}
}
if (slice == 0)
return slice(dimension);
return Nd4j.createComplex(
data,
ArrayUtil.removeIndex(shape, dimension),
ArrayUtil.removeIndex(stride, dimension),
offset, ordering
);
}
@Override
protected void initShape(int[] shape) {
this.shape = shape;
if(this.shape.length == 1) {
rows = 1;
columns = this.shape[0];
}
else if(this.shape().length == 2) {
if(shape[0] == 1) {
this.shape = new int[1];
this.shape[0] = shape[1];
rows = 1;
columns = shape[1];
}
else {
rows = shape[0];
columns = shape[1];
}
}
//default row vector
else if(this.shape.length == 1) {
columns = this.shape[0];
rows = 1;
}
//null character
if(this.ordering == '\u0000')
this.ordering = Nd4j.order();
this.length = ArrayUtil.prod(this.shape);
if(this.stride == null) {
if(ordering == NDArrayFactory.FORTRAN)
this.stride = ArrayUtil.calcStridesFortran(this.shape,2);
else
this.stride = ArrayUtil.calcStrides(this.shape,2);
}
//recalculate stride: this should only happen with row vectors
if(this.stride.length != this.shape.length) {
if(ordering == NDArrayFactory.FORTRAN)
this.stride = ArrayUtil.calcStridesFortran(this.shape,2);
else
this.stride = ArrayUtil.calcStrides(this.shape,2);
}
}
protected INDArray newShape(int[] newShape, char ordering) {
if(Arrays.equals(newShape,this.shape()))
return this;
else if(Shape.isVector(newShape) && isVector()) {
if(isRowVector() && Shape.isColumnVectorShape(newShape)) {
return Nd4j.createComplex(data,newShape,new int[]{stride[0],1},offset);
}
else if(isColumnVector() && Shape.isRowVectorShape(newShape)) {
return Nd4j.createComplex(data,newShape,new int[]{stride[1]},offset);
}
}
IComplexNDArray newCopy = this;
int[] newStrides = null;
//create a new copy of the ndarray
if(shape().length > 1 && ((ordering == NDArrayFactory.C && this.ordering != NDArrayFactory.C) ||
(ordering == NDArrayFactory.FORTRAN && this.ordering != NDArrayFactory.FORTRAN))) {
newStrides = noCopyReshape(newShape,ordering);
if(newStrides == null) {
newCopy = Nd4j.createComplex(shape(),ordering);
for(int i = 0; i < vectorsAlongDimension(0); i++) {
IComplexNDArray copyFrom = vectorAlongDimension(i,0);
IComplexNDArray copyTo = newCopy.vectorAlongDimension(i,0);
for(int j = 0; j < copyFrom.length(); j++) {
copyTo.putScalar(j,copyFrom.getDouble(i));
}
}
}
}
//needed to copy data
if(newStrides == null)
newStrides = Nd4j.getComplexStrides(newShape,ordering);
return Nd4j.createComplex(newCopy.data(), newShape, newStrides, offset);
}
/**
* Replicate and tile array to fill out to the given shape
*
* @param shape the new shape of this ndarray
* @return the shape to fill out to
*/
@Override
public IComplexNDArray repmat(int[] shape) {
int[] newShape = ArrayUtil.copy(shape());
assert shape.length <= newShape.length : "Illegal shape: The passed in shape must be <= the current shape length";
for(int i = 0; i < shape.length; i++)
newShape[i] *= shape[i];
IComplexNDArray result = Nd4j.createComplex(newShape);
//nd copy
if(isScalar()) {
for(int i = 0; i < result.length(); i++) {
result.put(i,getScalar(0));
}
}
else if(isMatrix()) {
for (int c = 0; c < shape()[1]; c++) {
for (int r = 0; r < shape()[0]; r++) {
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < columns(); j++) {
result.put(r * rows() + i, c * columns() + j, getScalar(i, j));
}
}
}
}
}
else {
int[] sliceRepmat = ArrayUtil.removeIndex(shape,0);
for(int i = 0; i < result.slices(); i++) {
result.putSlice(i,repmat(sliceRepmat));
}
}
return result;
}
/**
* Assign all of the elements in the given
* ndarray to this ndarray
*
* @param arr the elements to assign
* @return this
*/
@Override
public IComplexNDArray assign(IComplexNDArray arr) {
if(!arr.isScalar())
LinAlgExceptions.assertSameShape(this, arr);
IComplexNDArray linear = linearView();
IComplexNDArray otherLinear = arr.linearView();
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,otherLinear.getComplex(i));
}
return this;
}
/**
* Get whole rows from the passed indices.
*
* @param rindices
*/
@Override
public IComplexNDArray getRows(int[] rindices) {
INDArray rows = Nd4j.create(rindices.length, columns());
for(int i = 0; i < rindices.length; i++) {
rows.putRow(i,getRow(rindices[i]));
}
return (IComplexNDArray) rows;
}
@Override
public IComplexNDArray put(NDArrayIndex[] indices, IComplexNumber element) {
return put(indices,Nd4j.scalar(element));
}
@Override
public IComplexNDArray put(NDArrayIndex[] indices, IComplexNDArray element) {
if(Indices.isContiguous(indices)) {
IComplexNDArray get = get(indices);
IComplexNDArray linear = get.linearView();
if(element.isScalar()) {
for(int i = 0; i < linear.length(); i++) {
linear.putScalar(i,element.getComplex(0));
}
}
if(Shape.shapeEquals(element.shape(),get.shape()) || element.length() <= get.length()) {
IComplexNDArray elementLinear = element.linearView();
for(int i = 0; i < elementLinear.length(); i++) {
linear.putScalar(i,elementLinear.getComplex(i));
}
}
}
else {
if(isVector()) {
assert indices.length == 1 : "Indices must only be of length 1.";
assert element.isScalar() || element.isVector() : "Unable to assign elements. Element is not a vector.";
assert indices[0].length() == element.length() : "Number of specified elements in index does not match length of element.";
int[] assign = indices[0].indices();
for(int i = 0; i < element.length(); i++) {
putScalar(assign[i],element.getComplex(i));
}
return this;
}
if(element.isVector())
slice(indices[0].indices()[0]).put(Arrays.copyOfRange(indices,1,indices.length),element);
else {
for(int i = 0; i < element.slices(); i++) {
INDArray slice = slice(indices[0].indices()[i]);
slice.put(Arrays.copyOfRange(indices,1,indices.length),element.slice(i));
}
}
}
return this;
}
@Override
public IComplexNDArray put(NDArrayIndex[] indices, Number element) {
return put(indices,Nd4j.scalar(element));
}
@Override
public IComplexNDArray putScalar(int i, IComplexNumber value) {
int idx = linearIndex(i);
data.put(idx,value.realComponent().doubleValue());
data.put(idx + 1, value.imaginaryComponent().doubleValue());
return this;
}
/**
* Get the vector along a particular dimension
*
* @param index the index of the vector to getScalar
* @param dimension the dimension to getScalar the vector from
* @return the vector along a particular dimension
*/
@Override
public IComplexNDArray vectorAlongDimension(int index, int dimension) {
assert dimension <= shape.length : "Invalid dimension " + dimension;
if(ordering == NDArrayFactory.C) {
if(dimension == shape.length - 1 && dimension != 0) {
if (size(dimension) == 1)
return Nd4j.createComplex(data,
new int[]{1, shape[dimension]}
, ArrayUtil.removeIndex(stride, 0),
offset + index * 2);
else
return Nd4j.createComplex(data,
new int[]{1, shape[dimension]}
, ArrayUtil.removeIndex(stride, 0),
offset + index * stride[0]);
}
else if(dimension == 0)
return Nd4j.createComplex(data,
new int[]{shape[dimension], 1}
, new int[]{stride[dimension], 1},
offset + index * 2);
if(size(dimension) == 0)
return Nd4j.createComplex(data,
new int[]{shape[dimension], 1}
, new int[]{stride[dimension], 1},
offset + index * 2);
return Nd4j.createComplex(data,
new int[]{shape[dimension], 1}
, new int[]{stride[dimension], 1},
offset + index * 2 * stride[0]);
}
else if(ordering == NDArrayFactory.FORTRAN) {
if(dimension == shape.length - 1 && dimension != 0) {
if(size(dimension) == 1) {
return Nd4j.createComplex(data,
new int[]{1, shape[dimension]}
, ArrayUtil.removeIndex(stride, 0),
offset + index * 2);
}
else
return Nd4j.createComplex(data,
new int[]{1, shape[dimension]}
, ArrayUtil.removeIndex(stride, 0),
offset + index * 2 * stride[0]);
}
if(size(dimension) == 1) {
return Nd4j.createComplex(data,
new int[]{1, shape[dimension]}
, ArrayUtil.removeIndex(stride, 0),
offset + index * 2);
}
else
return Nd4j.createComplex(data,
new int[]{shape[dimension], 1}
, new int[]{stride[dimension], 1},
offset + index * 2 * stride[0]);
}
throw new IllegalStateException("Illegal ordering..none declared");}
/**
* Cumulative sum along a dimension
*
* @param dimension the dimension to perform cumulative sum along
* @return the cumulative sum along the specified dimension
*/
@Override
public IComplexNDArray cumsumi(int dimension) {
if(isVector()) {
IComplexNumber s = Nd4j.createDouble(0, 0);
for (int i = 0; i < length; i++) {
s .addi(getComplex(i));
putScalar(i, s);
}
}
else if(dimension == Integer.MAX_VALUE || dimension == shape.length - 1) {
IComplexNDArray flattened = ravel().dup();
IComplexNumber prevVal = flattened.getComplex(0);
for(int i = 1; i < flattened.length(); i++) {
IComplexNumber d = prevVal.add((flattened.getComplex(i)));
flattened.putScalar(i,d);
prevVal = d;
}
return flattened;
}
else {
for(int i = 0; i < vectorsAlongDimension(dimension); i++) {
IComplexNDArray vec = vectorAlongDimension(i,dimension);
vec.cumsumi(0);
}
}
return this;
}
/**
* Dimshuffle: an extension of permute that adds the ability
* to broadcast various dimensions.
*
* See theano for more examples.
* This will only accept integers and xs.
*
* An x indicates a dimension should be broadcasted rather than permuted.
*
* @param rearrange the dimensions to swap to
* @return the newly permuted array
*/
@Override
public IComplexNDArray dimShuffle(Object[] rearrange,int[] newOrder,boolean[] broadCastable) {
assert broadCastable.length == shape.length : "The broadcastable dimensions must be the same length as the current shape";
boolean broadcast = false;
Set