All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mikera.vectorz.impl.GrowableIndexedVector Maven / Gradle / Ivy

Go to download

Fast double-precision vector and matrix maths library for Java, supporting N-dimensional numeric arrays.

There is a newer version: 0.67.0
Show newest version
package mikera.vectorz.impl;

import java.util.Iterator;

import mikera.indexz.GrowableIndex;
import mikera.indexz.Index;
import mikera.vectorz.AVector;
import mikera.vectorz.GrowableVector;
import mikera.vectorz.Tools;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;

/**
 * Implementation for a sparse indexed vector that can accumulate index/value pairs efficiently (in order) 
 * 
 * Length grows if elements are added beyond the end of the vector
 * 
 * @author Mike
 */
public class GrowableIndexedVector extends AVector implements ISparseVector {
	private static final long serialVersionUID = 441979517032171392L;

	private int length;
	private final GrowableIndex index;
	private final GrowableVector data;
	
	private GrowableIndexedVector(int length, GrowableIndex index, GrowableVector data) {
		this.length=length;
		this.index=index;
		this.data=data;
	}
	
	private GrowableIndexedVector(int length) {
		this.length=length;
		this.index=new GrowableIndex();
		this.data=new GrowableVector();
	}
	
	private GrowableIndexedVector() {
		this(0);
	}
	
	/**
	 * Creates a GrowableIndexedVector from the specified Iterable object
	 * @param iterable An Iterable containing java.lang.Number instances
	 * @return
	 */
	public static GrowableIndexedVector create(Iterable iterable) {
		GrowableIndexedVector v=new GrowableIndexedVector();
		for (Object o: iterable) {
			v.length++;
			double d=Tools.toDouble(o);
			if (d!=0.0) {
				v.append(v.length-1,d);
			}
		}
		return v;
	}
	
	/**
	 * Creates a GrowableIndexedVector from the specified Iterable object
	 * @param iterable An Iterable containing java.lang.Number instances
	 * @return
	 */
	public static GrowableIndexedVector create(AVector v) {
		if (v instanceof ISparseVector) {
			return create((ISparseVector) v);
		}
		return new GrowableIndexedVector(v.length(),GrowableIndex.wrap(v.nonZeroIndices().clone()),GrowableVector.wrap(v.nonZeroValues().clone()));
	}
	
	public static GrowableIndexedVector create(ISparseVector v) {
		return new GrowableIndexedVector(v.length(),GrowableIndex.create(v.nonSparseIndex()),GrowableVector.create(v.nonSparseValues()));
	}

	/**
	 * Creates a GrowableIndexedVector from the specified Iterator object
	 * @param iterator An Iterator over java.lang.Number instances
	 * @return
	 */
	public static GrowableIndexedVector create(Iterator iterator) {
		GrowableIndexedVector v=new GrowableIndexedVector();
		while (iterator.hasNext()) {
			v.length++;
			double d=Tools.toDouble(iterator.next());
			if (d!=0.0) {
				v.append(v.length-1,d);
			}
		}
		return v;
	}
	
	/**
	 * Creates a zero-filled GrowableIndexedVector with the specified initial length
	 * @param len
	 * @return
	 */
	public static GrowableIndexedVector createLength(int len) {
		return new GrowableIndexedVector(len);
	}

	@Override
	public double get(int i) {
		checkIndex(i);
		int ix=index.indexPosition(i);
		if (ix<0) return 0.0;
		return data.get(ix);
	}
	
	/**
	 * Adds a value to this GrawableIndexedVector at the specified position.
	 * Grows the vector if required.
	 * @param i
	 * @param value
	 */
	public void append(int i, double value) {
		index.checkedAppend(i);
		data.append(value);
		if (i>=length) length=i+1;
	}

	@Override
	public void set(int i, double value) {
		if (i<0) throw new IndexOutOfBoundsException(ErrorMessages.invalidIndex(this, i));
		if (i>=length) {
			append(i,value);
			return;
		}
		int ix=index.indexPosition(i);
		if (ix<0) {
			int pos=index.include(i);
			if (index.length()>data.length()) {
				data.insert(pos,value);
			} else {
				data.set(pos,value);
			}
		} else {
			data.unsafeSet(ix, value);
		}
	}
	
	public void append(double v) {
		set(length,v);
	}
	
	@Override
	public boolean isFullyMutable() {
		return true;
	}

	@Override
	public double dotProduct(double[] data, int offset) {
		return toSparseIndexedVector().dotProduct(data,offset);
	}

	@Override
	public SparseIndexedVector toSparseIndexedVector() {
		return SparseIndexedVector.wrap(length, Index.create(index), data.toDoubleArray());
	}

	@Override
	public AVector exactClone() {
		return new GrowableIndexedVector(length,index.exactClone(), data.exactClone());
	}
	
	@Override
	public SparseIndexedVector sparseClone() {
		return toSparseIndexedVector();
	}
	
	@Override
	public SparseIndexedVector sparse() {
		// we do this to ensure a "full" implementation is used
		return toSparseIndexedVector();
	}

	public int nonSparseElementCount() {
		return index.length();
	}

	@Override
	public AVector nonSparseValues() {
		return data;
	}

	@Override
	public Index nonSparseIndex() {
		return Index.create(index);
	}

	public boolean includesIndex(int i) {
		return index.indexPosition(i)>=0;
	}

	@Override
	public void validate() {
		int il=index.length();
		int dl=data.length();
		if (il!=dl) throw new VectorzException("Mismatched index and data length!");
		if (il>length) throw new VectorzException("Index larger than length!");
		if (dl>length) throw new VectorzException("Data larger than length!");
		if (index.get(il-1)>=length) throw new VectorzException("Last element beyond length!");
	}

	@Override
	public int length() {
		return length;
	}
	
	/**
	 * Sets the length of this vector. 
	 * @return
	 */
	public void setLength(int length) {
		if ((length>this.length)||(index.last()




© 2015 - 2025 Weber Informatics LLC | Privacy Policy