package mikera.vectorz.impl; import mikera.vectorz.AVector; import mikera.vectorz.util.VectorzException; public final class StridedVector extends AStridedVector { private static final long serialVersionUID = 5807998427323932401L; private final int offset; private final int stride; private StridedVector(double[] data, int offset, int length, int stride) { super(length,data); if ((offset<0)) throw new IndexOutOfBoundsException(); if (length>0) { // check last element is in the array int lastOffset=(offset+(length-1)*stride); if ((lastOffset>=data.length)||(lastOffset<0)) throw new IndexOutOfBoundsException("StridedVector ends outside array"); } this.offset=offset; this.stride=stride; } public static StridedVector wrapStrided(double[] data, int offset, int length, int stride) { return new StridedVector(data,offset,length,stride); } public static StridedVector wrap(double[] data, int offset, int length, int stride) { return wrapStrided(data,offset,length,stride); } @Override public boolean isView() { return true; } @Override public boolean isFullyMutable() { return true; } @Override public boolean isMutable() { return true; } @Override public double dotProduct(AVector v) { int length=checkLength(v.length()); if (v instanceof ADenseArrayVector) { ADenseArrayVector av=(ADenseArrayVector) v; return dotProduct(av.getArray(),av.getArrayOffset()); } double result=0.0; for (int i=0; i<length; i++) { result+=data[offset+i*stride]*v.unsafeGet(i); } return result; } @Override public double dotProduct(double[] ds, int off) { double result=0.0; for (int i=0; i<length; i++) { result+=data[offset+i*stride]*ds[i+off]; } return result; } @Override public void set(AVector v) { int length=checkSameLength(v); v.copyTo(0, data, offset, length, stride); } @Override public void add(AVector v) { if (v instanceof AStridedVector) { add((AStridedVector)v); return; } super.add(v); } public void add(AStridedVector v) { int length=checkLength(v.length()); double[] vdata=v.getArray(); int voffset=v.getArrayOffset(); int vstride=v.getStride(); for (int i=0; i<length; i++) { data[offset+i*stride]+=vdata[voffset+i*vstride]; } } @Override public int getStride() { return stride; } @Override public int getArrayOffset() { return offset; } @Override public AVector subVector(int start, int length) { int len=checkRange(start,length); if (length==0) return Vector0.INSTANCE; if (length==len) return this; if (length==1) { return ArraySubVector.wrap(data, offset+start*stride, 1); } return wrapStrided(data,offset+start*stride,length,stride); } @Override public double get(int i) { checkIndex(i); return data[offset+i*stride]; } @Override public void set(int i, double value) { checkIndex(i); data[offset+i*stride]=value; } @Override public double unsafeGet(int i) { return data[offset+i*stride]; } @Override public void unsafeSet(int i, double value) { data[offset+i*stride]=value; } @Override public void addAt(int i, double value) { data[offset+i*stride]+=value; } @Override public void getElements(double[] dest, int destOffset) { for (int i=0; i<length; i++) { dest[destOffset+i]=data[offset+(i*stride)]; } } @Override public StridedVector exactClone() { double[] data=this.data.clone(); return wrapStrided(data,offset,length,stride); } @Override public void validate() { if (length>0) { if ((offset<0)||(offset>=data.length)) throw new VectorzException("offset out of bounds: "+offset); int lastIndex=offset+(stride*(length-1)); if ((lastIndex<0)||(lastIndex>=data.length)) throw new VectorzException("lastIndex out of bounds: "+lastIndex); } super.validate(); } @Override protected int index(int i) { return offset+i*stride; } }