package rpn.vc;

import real.Real;
import rpn.basic.Item;
import rpn.basic.IntItem;
import rpn.basic.ErrItem;
import rpn.basic.ArrayItem;
import rpn.basic.DoubleValue;
import rpn.basic.CalcErr;
import rpn.doubles.DoubleItem;

import rpn.Calculator;

public class VectorItem extends ArrayItem {
	double x[];
	
	public VectorItem(Calculator ca, double x[]) {
		super(ca);
		this.x = x;
	}
	
	public int size() {
		return(x.length);
	}
	
	// range assumed OK
	public Item get(int i) {
		return(new DoubleItem(ca, x[i]));
	}
	
	public void put(Item a, int i) {
		if (a instanceof DoubleValue) {
			if (0 <= i && i < x.length) {
				double y = ((DoubleValue) a).doubleValue();
				x[i] = y;
			} else {
				ca.error(this, CalcErr.Range);
			}
		} else {
			ca.error(this, CalcErr.Type);
		}
	}
	
	public Item plus(VectorItem it) {
		double y[] = it.x;
		int nx = x.length, ny = y.length;
		if (nx == ny) {
			double z[] = new double[nx];
			for (int i=0;i<nx;i++) {
				z[i] = x[i] + y[i];
			}
			return(new VectorItem(ca, z));
		} else {
			return(new ErrItem(ca, this, CalcErr.UnmatchedDims));
		}
		
	}
	
	public Item minus(VectorItem it) {
		double y[] = it.x;
		int nx = x.length, ny = y.length;
		if (nx == ny) {
			double z[] = new double[nx];
			for (int i=0;i<nx;i++) {
				z[i] = x[i] - y[i];
			}
			return(new VectorItem(ca, z));
		} else {
			return(new ErrItem(ca, this, CalcErr.UnmatchedDims));
		}
		
	}
	
	public Item times(VectorItem it) {
		double y[] = it.x;
		int nx = x.length, ny = y.length;
		if (nx == ny) {
			double z = 0.0;
			for (int i=0;i<nx;i++) {
				z += x[i]*y[i];
			}
			return(new DoubleItem(ca, z));
		} else {
			return(new ErrItem(ca, this, CalcErr.UnmatchedDims));
		}
		
	}
	
	public Item times(double y) {
		int nx = x.length;
		double z[] = new double[nx];
		for (int i=0;i<nx;i++) {
			z[i] = x[i]*y;
		}
		return(new VectorItem(ca, z));
	}
	
	public Item times(IntItem it) {
		double y = (double) it.n;
		int nx = x.length;
		double z[] = new double[nx];
		for (int i=0;i<nx;i++) {
			z[i] = x[i]*y;
		}
		return(new VectorItem(ca, z));
	}
	
	public Item cross(VectorItem it) {
		double y[] = it.x;
		int nx = x.length;
		int ny = y.length;
		double z[] = new double[nx];
		// x[0] x[1] x[2]
		// y[0] y[1] y[2]
		if (nx == ny && nx == 3) {
			z[0] = x[1]*y[2] - x[2]*y[1];
			z[1] = x[2]*y[0] - x[0]*y[2];
			z[2] = x[0]*y[1] - x[1]*y[0];
			return(new VectorItem(ca, z));
		} else {
			return(new ErrItem(ca, this, CalcErr.InvalidDim));
		}
	}
	
	public Item coordinate(int i) {
		if (0 <= i && i < x.length) {
			double y = x[i];
			return(new DoubleItem(ca, y));
		} else {
			return(new ErrItem(ca, this, CalcErr.Range));
		}
	}
	
	public String toString() {
		String s = new String("[");
		for (int i=0;i<x.length;i++) {
			s += " ";
			s += Real.toString(x[i], ca.fix, ca.fix);
		}
		s += " ]";
		return(s);
	}
}