/* * Vector.java * * Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard * * This file is part of BEAST. * See the NOTICE file distributed with this work for additional * information regarding copyright ownership and licensing. * * BEAST is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * BEAST is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with BEAST; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301 USA */ package dr.math.matrixAlgebra; /** * Vector implementation * * @author Didier H. Besset */ public class Vector { protected double[] components; /** * Create a vector of given dimension. * NOTE: The supplied array of components must not be changed. * * @param comp double[] */ public Vector(double comp[]) throws NegativeArraySizeException { int n = comp.length; if (n <= 0) throw new NegativeArraySizeException( "Vector components cannot be empty"); components = new double[n]; System.arraycopy(comp, 0, components, 0, n); } public Vector(int comp[]) throws NegativeArraySizeException { int n = comp.length; if (n <= 0) throw new NegativeArraySizeException( "Vector components cannot be empty"); components = new double[n]; // System.arraycopy( comp, 0, components, 0, n); for (int i = 0; i < n; i++) components[i] = comp[i]; } /** * Create a vector of given dimension. * * @param dimension int dimension of the vector; must be positive. */ public Vector(int dimension) throws NegativeArraySizeException { if (dimension <= 0) throw new NegativeArraySizeException( "Requested vector size: " + dimension); components = new double[dimension]; // clear(); // Java automatically zeros new vectors } /** * @param v DHBmatrixAlgebra.DhbVector * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public void accumulate(double[] x) throws IllegalDimension { if (this.dimension() != x.length) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + x.length + "-dimension array"); for (int i = 0; i < this.dimension(); i++) components[i] += x[i]; } /** * @param v DHBmatrixAlgebra.DhbVector * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public void accumulate(Vector v) throws IllegalDimension { if (this.dimension() != v.dimension()) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + v.dimension() + "-dimension vector"); for (int i = 0; i < this.dimension(); i++) components[i] += v.components[i]; } /** * @param v DHBmatrixAlgebra.DhbVector * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public void accumulateNegated(double[] x) throws IllegalDimension { if (this.dimension() != x.length) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + x.length + "-dimension array"); for (int i = 0; i < this.dimension(); i++) components[i] -= x[i]; } /** * @param v DHBmatrixAlgebra.DhbVector * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public void accumulateNegated(Vector v) throws IllegalDimension { if (this.dimension() != v.dimension()) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + v.dimension() + "-dimension vector"); for (int i = 0; i < this.dimension(); i++) components[i] -= v.components[i]; } /** * @param v DHBmatrixAlgebra.DhbVector * @return DHBmatrixAlgebra.DhbVector sum of the vector with * the supplied vector * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public Vector add(Vector v) throws IllegalDimension { if (this.dimension() != v.dimension()) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + v.dimension() + "-dimension vector"); double[] newComponents = new double[this.dimension()]; for (int i = 0; i < this.dimension(); i++) newComponents[i] = components[i] + v.components[i]; return new Vector(newComponents); } /** * Sets all components of the receiver to 0. */ public void clear() { for (int i = 0; i < components.length; i++) components[i] = 0; } /** * @param n int * @return double */ public double component(int n) { return components[n]; } public void set(int n, double value) { components[n] = value; } /** * Returns the dimension of the vector. * * @return int */ public int dimension() { return components.length; } /** * @param v DHBmatrixAlgebra.DhbVector * @return true if the supplied vector is equal to the receiver */ public boolean equals(Vector v) { int n = this.dimension(); if (v.dimension() != n) return false; for (int i = 0; i < n; i++) { if (v.components[i] != components[i]) return false; } return true; } /** * Computes the norm of a vector. */ public double norm() { double sum = 0; for (int i = 0; i < components.length; i++) sum += components[i] * components[i]; return Math.sqrt(sum); } /** * @param x double */ public Vector normalizedBy(double x) { for (int i = 0; i < this.dimension(); i++) components[i] /= x; return this; } /** * Computes the product of the vector by a number. * * @param d double * @return DHBmatrixAlgebra.DhbVector */ public Vector product(double d) { double newComponents[] = new double[components.length]; for (int i = 0; i < components.length; i++) newComponents[i] = d * components[i]; return new Vector(newComponents); } /** * Compute the scalar product (or dot product) of two vectors. * * @param v DHBmatrixAlgebra.DhbVector * @return double the scalar product of the receiver with the argument * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the dimension * of v is not the same. */ public double product(Vector v) throws IllegalDimension { int n = v.dimension(); if (components.length != n) throw new IllegalDimension( "Dot product with mismatched dimensions: " + components.length + ", " + n); return secureProduct(v); } /** * Computes the product of the transposed vector with a matrix * * @param a MatrixAlgebra.Matrix * @return MatrixAlgebra.DhbVector */ public Vector product(Matrix a) throws IllegalDimension { int n = a.rows(); int m = a.columns(); if (this.dimension() != n) throw new IllegalDimension( "Product error: transposed of a " + this.dimension() + "-dimension vector cannot be multiplied with a " + n + " by " + m + " matrix"); return secureProduct(a); } /** * @param x double */ public Vector scaledBy(double x) { for (int i = 0; i < this.dimension(); i++) components[i] *= x; return this; } /** * Compute the scalar product (or dot product) of two vectors. * No dimension checking is made. * * @param v DHBmatrixAlgebra.DhbVector * @return double the scalar product of the receiver with the argument */ protected double secureProduct(Vector v) { double sum = 0; for (int i = 0; i < v.dimension(); i++) sum += components[i] * v.components[i]; return sum; } /** * Computes the product of the transposed vector with a matrix * * @param a MatrixAlgebra.Matrix * @return MatrixAlgebra.DhbVector */ protected Vector secureProduct(Matrix a) { int n = a.rows(); int m = a.columns(); double[] vectorComponents = new double[m]; for (int j = 0; j < m; j++) { vectorComponents[j] = 0; for (int i = 0; i < n; i++) vectorComponents[j] += components[i] * a.components[i][j]; } return new Vector(vectorComponents); } /** * @param v DHBmatrixAlgebra.DhbVector * @return DHBmatrixAlgebra.DhbVector subtract the supplied vector * to the receiver * @throws DHBmatrixAlgebra.DhbIllegalDimension * if the vector * and supplied vector do not have the same dimension. */ public Vector subtract(Vector v) throws IllegalDimension { if (this.dimension() != v.dimension()) throw new IllegalDimension("Attempt to add a " + this.dimension() + "-dimension vector to a " + v.dimension() + "-dimension vector"); double[] newComponents = new double[this.dimension()]; for (int i = 0; i < this.dimension(); i++) newComponents[i] = components[i] - v.components[i]; return new Vector(newComponents); } /** * @param v MatrixAlgebra.DhbVector second vector to build tensor * product with. * @return MatrixAlgebra.Matrix tensor product with the specified * vector */ public Matrix tensorProduct(Vector v) { int n = dimension(); int m = v.dimension(); double[][] newComponents = new double[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) newComponents[i][j] = components[i] * v.components[j]; } return n == m ? new SymmetricMatrix(newComponents) : new Matrix(newComponents); } /** * @return double[] a copy of the components of the receiver. */ public double[] toComponents() { int n = dimension(); double[] answer = new double[n]; System.arraycopy(components, 0, answer, 0, n); return answer; } /** * Returns a string representation of the vector. * * @return java.lang.String */ public String toString() { StringBuffer sb = new StringBuffer(); char[] separator = {'[', ' '}; for (int i = 0; i < components.length; i++) { sb.append(separator); sb.append(components[i]); separator[0] = ','; } sb.append(']'); return sb.toString(); } public static Vector buildOneTimesElementVector(int dim, double element){ double[] component=new double[dim]; for (int i = 0; i <dim ; i++) { component[i]=element; } return new Vector(component); } }