package mikera.vectorz;

import java.nio.DoubleBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import mikera.arrayz.INDArray;
import mikera.indexz.AIndex;
import mikera.util.Rand;
import mikera.vectorz.impl.ADenseArrayVector;
import mikera.vectorz.impl.AStridedVector;
import mikera.vectorz.impl.ArraySubVector;
import mikera.vectorz.impl.AxisVector;
import mikera.vectorz.impl.RangeVector;
import mikera.vectorz.impl.RepeatedElementVector;
import mikera.vectorz.impl.SingleElementVector;
import mikera.vectorz.impl.SparseIndexedVector;
import mikera.vectorz.impl.StridedVector;
import mikera.vectorz.impl.Vector0;
import mikera.vectorz.impl.ZeroVector;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;
import us.bpsm.edn.parser.CollectionBuilder;
import us.bpsm.edn.parser.Parser;
import us.bpsm.edn.parser.Parsers;

public class Vectorz {

	private Vectorz(){}

	/**
	 * Constant tolerance used for testing double values
	 */
	public static final double TEST_EPSILON = 0.0000001;
	
	/**
	 * Specified the minimum length at which it is worthwhile creating sparse vectors rather than
	 * dense vectors. This acts as a hint to modify the behaviour of sparse vector construction functions.
	 */
	public static final int MIN_SPARSE_LENGTH=50;

	// threshold below which it is worthwhile making big vectors sparse
	private static final double SPARSE_DENSITY_THRESHOLD = 0.2;

	// ===========================
	// Factory functions
	
	/**
	 * Creates a vector using the given double data, using the most efficient dense representation.
	 * 
	 * @param data
	 * @return
	 */
	public static AVector create(double... data) {
		int n=data.length;
		switch (n) {
			case 0: return Vector0.INSTANCE;
			case 1: return Vector1.of(data);
			case 2: return Vector2.of(data);
			case 3: return Vector3.of(data);
			case 4: return Vector4.of(data);
			default: return Vector.of(data);
		}
	}
	
	/**
	 * Creates a joined vector that refers to the two underlying vectors
	 * 
	 * @param first
	 * @param second
	 * @return
	 */
	public static AVector join(AVector first, AVector second) {
		AVector result=first.join(second);
		assert(result.length()==first.length()+second.length());
		return result;
	}
	
	/**
	 * Join one or more vectors into a single concatenated vector
	 * @param vectors
	 * @return
	 */
	public static AVector join(AVector... vectors) {
		AVector result=vectors[0];
		for (int i=1; i vectors) {
		int count=vectors.size();
		AVector v=Vector0.INSTANCE;
		for (int i=0; i=Integer.MAX_VALUE) throw new IllegalArgumentException("Requested zero vector length too large: "+l);
		return ZeroVector.create((int)l);
	}
	
	/**
	 * Wraps a double array as a Vector instance. Changes to the double array will
	 * be reflected in the Vector
	 * 
	 * @param data
	 * @return
	 */
	public static Vector wrap(double... data) {
		return Vector.wrap(data);
	}
	
	public static AVector wrap(double[][] data) {
		if ((data.length)==0) return Vector0.INSTANCE;
		
		AVector v=Vector0.INSTANCE;
		for (int i=0; i(len*SPARSE_DENSITY_THRESHOLD)) {
			return Vector.create(v); // not enough sparsity to make worthwhile
		} else {
			return SparseIndexedVector.createWithIndices(v,ixs);
		}
	}
	
	/**
	 * Creates a sparse vector from an array of Object values
	 * @param values
	 * @return
	 */
	public static AVector createSparse(Object... values) {
		return SparseIndexedVector.create(values);
	}
	
	/**
	 * Creates a sparse vector from an array of Object values
	 * @param values
	 * @return
	 */
	public static AVector createSparse(Object data) {
		if (data instanceof INDArray) {
			INDArray a=(INDArray)data;
			if (a.dimensionality()!=1) throw new IllegalArgumentException("Can't convert to sparse vector: "+ErrorMessages.incompatibleShape(a));
			return createSparse(a.asVector());
		}
		return SparseIndexedVector.create(data);
	}
	
	/**
	 * Creates a mutable sparse vector from the data in the given vector. Selects the appropriate sparse
	 * vector type based on analysis of the element values.
	 * 
	 * @param v Vector containing sparse element data
	 * @return
	 */
	public static AVector createSparseMutable(int length) {
		if (length(len*SPARSE_DENSITY_THRESHOLD))) {
			return Vector.create(v); // not enough sparsity to make worthwhile, just copy
		} else {
			return SparseIndexedVector.create(v);
		}
	}

	/**
	 * Creates a new zero-filled vector of the same size as the given Vector.
	 * @param v
	 * @return
	 */
	public static AVector createSameSize(AVector v) {
		return newVector(v.length());
	}

	/**
	 * Creates a mutable clone of a given vector
	 * @param vector
	 * @return
	 */
	public static AVector create(AVector vector) {
		return vector.clone();
	}	
	
	/**
	 * Creates a mutable clone of a given vector
	 * @param vector
	 * @return
	 */
	public static AVector create(IVector vector) {
		return (AVector)vector.clone();
	}	
	
	/**
	 * Creates a new vector containing the values in the specified index
	 * @param index
	 * @return
	 */
	public static AVector create(AIndex index) {
		int n=index.length();
		Vector v=Vector.createLength(n);
		for (int i=0; i d) {
		int length=d.size();
		AVector v=Vectorz.newVector(length);
		for (int i=0; i d) {
		ArrayList al=new ArrayList();
		for (Object o:d) {
			al.add(o);
		}
		return create(al);
	}

	/**
	 * Returns the minimum-valued component in a vector
	 * @param v
	 * @return
	 */
	@Deprecated public static double minValue(AVector v) {
		return v.elementMin();
	}
	
	/**
	 * Returns the index of the minimum-valued component in a vector
	 * @param v
	 * @return
	 */
	@Deprecated public static int indexOfMinValue(AVector v) {
		int len=v.length();
		double min = v.get(0);
		int ind=0;
		for (int i=1; imax) {
				max=d;
				ind=i;
			}
		}
		return ind;
	}
	
	public static void invSqrt(AVector v) {
		if (v instanceof Vector) {invSqrt((Vector) v); return;}
		int len=v.length();
		for (int i=0; i) {
			return Vectorz.create((List)o);
		} else if (o instanceof Iterable) {
			return Vectorz.create((Iterable)o);
		}
		throw new UnsupportedOperationException("Cannot coerce to AVector: "+o.getClass());
	} 

	/**
	 * Create a mutable vector contain the sequence of integers from 0 to length-1
	 * 
	 * @param length The length of vector to create
	 * @return
	 */
	public static AVector createMutableRange(int length) {
		AVector v=Vectorz.newVector(length);
		for (int i=0; i 
 

Ads help maintain this website.