package mikera.vectorz;

import java.nio.DoubleBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import mikera.arrayz.INDArray;
import mikera.indexz.AIndex;
import mikera.indexz.Index;
import mikera.randomz.Hash;
import mikera.vectorz.impl.ADenseArrayVector;
import mikera.vectorz.util.DoubleArrays;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;


/**
 * General purpose vector of arbitrary length, backed by an densely packed double[] array.
 * 
 * This is the most efficient type for general purpose dense 1D vectors.
 * 
 * @author Mike
 *
 */
public final class Vector extends ADenseArrayVector {
	private static final long serialVersionUID = 6283741614665875877L;

	public static final Vector EMPTY = wrap(DoubleArrays.EMPTY);

	private Vector(double... values) {
		super(values.length,values);
	}
	
	private Vector(int length) {
		this(new double[length]);
	}

	/**
	 * Copy constructor from an arbitrary vector
	 * 
	 * @param source
	 */
	public Vector(AVector source) {
		this(source.toDoubleArray());
	}
	
	/**
	 * Wraps a double array into a Vector, does *no defensive copy* so use with caution
	 * @param source
	 * @return
	 */
	public static Vector wrap(double[] source) {
		return new Vector(source);
	}
	
	/**
	 * Creates a new Vector from the given double[] data. Takes a defensive copy.
	 */
	public static Vector create(double[] data) {
		if (data.length==0) return EMPTY;
		return wrap(data.clone());
	}
	
	public static Vector create(ArrayList al) {
		int n=al.size();
		Vector v=Vector.createLength(n);
		for (int i=0; i al) {
		int n=al.size();
		Vector v=Vector.createLength(n);
		for (int i=0; i iterable) {
		GrowableVector v=GrowableVector.create(iterable);
		return v.toVector();
	}
	
	/**
	 * Creates a Vector from the specified Iterator object
	 * @param iterator An Iterator over java.lang.Number instances
	 * @return
	 */
	public static Vector create(Iterator iterator) {
		GrowableVector v=GrowableVector.create(iterator);
		return v.toVector();
	}
	
	@SuppressWarnings("unchecked")
	public static Vector create(Object o) {
		if (o instanceof AVector) {
			return create((AVector)o);
		} else if (o instanceof List) {
			return create((List)o);
		} else if (o.getClass().isArray()) {
			
			return create((List)o);
		} else if (o instanceof Iterable){
			return create((Iterable)o);
		} else if (o instanceof Iterator){
			return create((Iterator)o);
		} 
		Class ec=o.getClass().getComponentType();
		if (ec!=null) {
			if (ec.isPrimitive()) {
				if (ec==Double.TYPE) return create((double[])o);
			} 
		}
		throw new IllegalArgumentException(ErrorMessages.cantCreateVector(o));
	}
	
	/**
	 * Creates a new Vector from the given double[] data. Takes a defensive copy.
	 */
	public static Vector create(double[] data, int start, int length) {
		return wrap(DoubleArrays.copyOf(data,start,length));
	}
	
	/**
	 * Creates a new vector using the elements in the specified vector.
	 * Truncates or zero-pads the data as required to fill the new vector
	 * @param data
	 * @return
	 */
	public static Vector createFromVector(AVector source, int length) {
		Vector v=Vector.createLength(length);
		int n=Math.min(length, source.length());
		source.copyTo(0, v.data, 0, n);
		return v;
	}
	
	/**
	 * Create a vector with specific component values. 
	 * Creates a copy of the value array
	 * @param values
	 * @return
	 */
	public static Vector of(double... values) {
		return create(values);
	}
	
	/**
	 * Create an empty (zero-filled) vector of a specified length
	 * @param length
	 * @return
	 */
	public static Vector createLength(int length) {
		if (length<1) {
		  if (length<0) throw new IllegalArgumentException(ErrorMessages.illegalSize(length));
		  return EMPTY;
		}
		return new Vector(length);
	}

	public static Vector create(AVector a) {
		return new Vector(a.toDoubleArray());
	}
	
	public static Vector create(INDArray a) {
		return new Vector(a.toDoubleArray());
	}
	
	public static Vector create(AIndex a) {
		int n=a.length();
		Vector v=createLength(n);
		for (int i=0; i=0);
		assert(srcOffset+length<=src.length());
		double[] srcData=src.getArray();
		int relativeOffset=src.getArrayOffset()+srcOffset;
		for (int i = 0; i < length; i++) {
			data[i] += srcData[relativeOffset + i];
		}
	}
	
	@Override
	public void addMultiple(ADenseArrayVector v, double factor) {
		checkSameLength(v);
		v.addMultipleToArray(factor,data, 0);
	}
	
	@Override
	public void add(AVector v) {
		checkSameLength(v);
		v.addToArray(data, 0);
	}
	
	@Override
	public void add(double[] srcData, int srcOffset) {
		DoubleArrays.add(srcData, srcOffset, data, 0, length);
	}
	
	@Override
	public void scaleAdd(double factor, double constant) {
		for (int i=0; i 

Ads help maintain this website.