/*  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package jdistlib.math;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static java.lang.Math.abs;
import static java.lang.Math.exp;
import static java.lang.Math.log;
import static java.lang.Math.log1p;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
import static jdistlib.util.Utilities.sort;

/**
 * 
 * @author Roby Joehanes
 *
 */
public class VectorMath {
	public static final double[] vpow(double x, double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = pow(x, e[i]);
		return v;
	}

	public static final double[] vpow(double[] x, double e) {
		double[] v = new double[x.length];
		for (int i = 0; i < x.length; i++)
			v[i] = pow(x[i], e);
		return v;
	}

	public static final double[] vpow(double[] x, double[] e) {
		if (x.length != e.length)
			throw new RuntimeException();
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = pow(x[i], e[i]);
		return v;
	}

	public static final double[] vpow(double x, int[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = pow(x, e[i]);
		return v;
	}

	public static final double[] vplus(double[] a, double[] b) {
		if (a.length != b.length)
			throw new RuntimeException();
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]+b[i];
		return v;
	}

	public static final double[] vplus(double a, double[] b) {
		double[] v = new double[b.length];
		for (int i = 0; i < b.length; i++)
			v[i] = a+b[i];
		return v;
	}

	public static final double[] vplus(double[] a, double b) {
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]+b;
		return v;
	}

	public static final double[] vmin(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = -e[i];
		return v;
	}

	public static final double[] vmin(double[] a, double[] b) {
		if (a.length != b.length)
			throw new RuntimeException();
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]-b[i];
		return v;
	}

	public static final double[] vmin(double[] a, double b) {
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]-b;
		return v;
	}

	public static final double[] vmin(double a, double[] b) {
		double[] v = new double[b.length];
		for (int i = 0; i < b.length; i++)
			v[i] = a-b[i];
		return v;
	}

	public static final double[] vtimes(double a, double[] b) {
		double[] v = new double[b.length];
		for (int i = 0; i < b.length; i++)
			v[i] = a*b[i];
		return v;
	}

	public static final double[] vtimes(double[] a, double b) {
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]*b;
		return v;
	}

	public static final double[] vtimes(double[] a, double[] b) {
		if (a.length != b.length)
			throw new RuntimeException();
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]*b[i];
		return v;
	}

	public static final double[] vsq(double[] a) {
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]*a[i];
		return v;
	}

	public static final double[] vdiv(double[] a, double b) {
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]/b;
		return v;
	}

	public static final double[] vdiv(double a, double[] b) {
		double[] v = new double[b.length];
		for (int i = 0; i < b.length; i++)
			v[i] = a/b[i];
		return v;
	}

	public static final double[] vdiv(double[] a, double[] b) {
		if (a.length != b.length)
			throw new RuntimeException();
		double[] v = new double[a.length];
		for (int i = 0; i < a.length; i++)
			v[i] = a[i]/b[i];
		return v;
	}

	public static final double[] vcomp(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = 1-e[i];
		return v;
	}

	public static final double[] vabs(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = abs(e[i]);
		return v;
	}

	public static final double[] vexp(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = exp(e[i]);
		return v;
	}

	public static final double[] vlog(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = log(e[i]);
		return v;
	}

	public static final double[] vlog1pComps(double[] e) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = log1p(-e[i]);
		return v;
	}

	public static final double[] vsignif(double[] e, int digits) {
		double[] v = new double[e.length];
		for (int i = 0; i < e.length; i++)
			v[i] = MathFunctions.signif(e[i], digits);
		return v;
	}

	public static final double[] diff(double[] e, int lag, int order) {
		double[] v = new double[e.length];
		System.arraycopy(e, 0, v, 0, e.length);
		int vlen = v.length;
		for (int i = 0; i < order; i++, vlen -= lag)
			for (int j = lag; j < vlen; j++)
				v[j - lag] = v[j] - v[j - lag];
		e = new double[e.length - lag * order];
		System.arraycopy(v, 0, e, 0, e.length);
		return e;
	}

	public static final double[] diff(double[] e, int lag) {
		return diff(e, lag, 1);
	}

	public static final double[] diff(double[] e) {
		return diff(e, 1, 1);
	}

	public static final boolean allFinite(double[] e) {
		for (double _e : e)
			if (MathFunctions.isInfinite(_e))
				return false;
		return true;
	}

	public static final boolean allLt(double[] e, double v) {
		for (double _e : e)
			if (_e >= v)
				return false;
		return true;
	}

	public static final boolean allGt(double[] e, double v) {
		for (double _e : e)
			if (_e <= v)
				return false;
		return true;
	}

	public static final boolean allEq(double[] e, double v) {
		for (double _e : e)
			if (_e != v)
				return false;
		return true;
	}

	public static final boolean allEqual(double[] e, double[] v) {
		if (e.length != v.length)
			throw new RuntimeException();
		int n = e.length;
		for (int i = 0; i < n; i++)
			if (e[i] != v[i])
				return false;
		return true;
	}

	/**
	 * Find quantile given a sorted data of array (Definition 7)
	 * @param sortedData This data is assumed to be presorted! Use quantile0 if you want to use unsorted data!
	 * @param quantile must be 0 <= quantile <= 1
	 * @return quantile value
	 */
	public static final double quantile(double[] sortedData, double quantile) {
		double index = (sortedData.length - 1) * quantile;
		int
			lo = (int) Math.floor(index),
			hi = (int) Math.ceil(index);
		if (lo < 0)
			return 0;
		double
			h = index - lo,
			lowerQ = sortedData[lo],
			result = h == 0 ? lowerQ : (1 - h) * lowerQ + h * sortedData[hi];
		return result;
	}

	/**
	 * Find quantile given a sorted data of array (Definition 7)
	 * @param sortedData This data is assumed to be presorted!
	 * @param quantile
	 * @return quantile values
	 */
	public static final double[] quantile(double[] sortedData, double[] quantile) {
		double[] v = new double[quantile.length];
		for (int i = 0; i < quantile.length; i++)
			v[i] = quantile(sortedData, quantile[i]);
		return v;
	}

	/**
	 * Find quantile in an array (Definition 7). Data is assumed to be unsorted
	 * @param e
	 * @param quantile must be 0 <= quantile <= 1
	 * @return quantile value
	 */
	public static final double quantile0(double[] e, double quantile) {
		int n = e.length;
		double[] r = new double[n];
		System.arraycopy(e, 0, r, 0, n);
		sort(r);
		return quantile(r, quantile);
	}

	/**
	 * Find quantile in an array (Definition 7). Data is assumed to be unsorted
	 * @param e
	 * @param quantile must be 0 <= quantile <= 1
	 * @return quantile values
	 */
	public static final double[] quantile0(double[] e, double[] quantile) {
		int n = e.length;
		double[] r = new double[n];
		System.arraycopy(e, 0, r, 0, n);
		sort(r);
		double[] v = new double[quantile.length];
		for (int i = 0; i < quantile.length; i++)
			v[i] = quantile(r, quantile[i]);
		return v;
	}

	public static final double mean(double[] e) {
		double sum = 0;
		int n = e.length;
		for (int i = 0; i < n; i++)
			sum += (e[i] / n); // guard against overflow
		return sum;
	}

	/**
	 * Return summary statistics
	 * @param e
	 * @return an array of 6 elements: Min, Q1, Median, Mean, Q3, Max
	 */
	public static final double[] summary(double[] e) {
		int n = e.length;
		double[] v = new double[e.length];
		System.arraycopy(e, 0, v, 0, n);
		sort(v);
		double[] s = quantile(v, new double[] {0.25, 0.5, 0.75});
		return new double[] {v[0], s[0], s[1], mean(v), s[2], v[n - 1]};
	}

	/**
	 * Get the median
	 * @param e does not need to be sorted
	 * @return median value
	 */
	public static final double median(double[] e) {
		int n = e.length;
		double[] v = new double[e.length];
		System.arraycopy(e, 0, v, 0, n);
		sort(v);
		return quantile(v, 0.5);
	}

	public static final double sd(double[] e) {
		double sum = 0, sumsq = 0;
		int n = e.length, nm1 = n-1;
		for (int i = 0; i < n; i++) {
			double v = e[i]; // guard against overflow
			sum += v / n;
			sumsq += v * v / nm1;
		}
		return sqrt(sumsq - (sum / nm1) * sum * n);
	}

	public static final double var(double[] e) {
		double sum = 0, sumsq = 0;
		int n = e.length, nm1 = n-1;
		for (int i = 0; i < n; i++) {
			double v = e[i]; // guard against overflow
			sum += v / n;
			sumsq += v * v / nm1;
		}
		return sumsq - (sum / nm1) * sum * n;
	}

	public static final double sum(double[] e) {
		double sum = 0;
		int n = e.length;
		for (int i = 0; i < n; i++)
			sum += e[i];
		return sum;
	}

	public static final double sum_kahan(double[] e) {
		double sum = e[0], c = 0;
		int n = e.length;
		for (int i = 1; i < n; i++) {
			double y = e[i] - c,
				t = sum + y;
			c = (t - sum) - y;
			sum = t;
		}
		return sum - c;
	}

	public static final double sum(Map e) {
		double sum = 0;
		for (int v: e.values())
			sum += v;
		return sum;
	}

	/**
	 * Compute the Median Absolute Deviation (MAD)
	 * @param e does not need to be sorted
	 * @return MAD value
	 */
	public static final double mad(double[] e) {
		int n = e.length;
		double[] v = new double[e.length];
		System.arraycopy(e, 0, v, 0, n);
		sort(v);
		double med = quantile(v, 0.5);
		for (int i = 0; i < n; i++)
			v[i] = abs(v[i] - med);
		return quantile(v, 0.5);
	}

	/**
	 * Standardize the value in x (i.e., (x - mean(x)) / sd(x))
	 * @param x
	 * @return standardized values
	 */
	public static final double[] standardize(double[] x) {
		double sum = 0, sumsq = 0;
		int n = x.length, nm1 = n-1;
		double[] new_x = new double[n];
		for (int i = 0; i < n; i++) {
			double v = x[i];
			sum += v / n; // guard against overflow
			sumsq += v * v / nm1;
		}
		sumsq = sqrt(sumsq - (sum / nm1) * sum * n);
		for (int i = 0; i < n; i++) {
			new_x[i] = (x[i] - sum) / sumsq;
		}
		return new_x;
	}

	public static final Map table(double[] e) {
		Map map = new HashMap();
		for (double _e : e) {
			String estr = String.valueOf(_e);
			Integer i = map.get(estr);
			map.put(estr, 1 + (i == null ? 0 : i.intValue()));
		}
		return map;
	}

	public static final  Map table(T[] e) {
		Map map = new HashMap();
		for (T _e : e) {
			String estr = String.valueOf(_e);
			Integer i = map.get(estr);
			map.put(estr, 1 + (i == null ? 0 : i.intValue()));
		}
		return map;
	}

	public static final double[] as_numeric(Collection ll) {
		int n = ll.size(), i = 0;
		double[] v = new double[n];
		for (String str: ll) {
			v[i] = Double.valueOf(str);
			i++;
		}
		return v;
	}

	public static final double[] cumsum(double[] e) {
		int n = e.length;
		double[] r = new double[n];
		r[0] = e[0];
		for (int i = 1; i < n; i++)
			r[i] = r[i-1] + e[i];
		return r;
	}

	public static final int[] cumsum(int[] e) {
		int n = e.length;
		int[] r = new int[n];
		r[0] = e[0];
		for (int i = 1; i < n; i++)
			r[i] = r[i-1] + e[i];
		return r;
	}

	public static final double max(double[] e) {
		int n = e.length;
		double mx = e[0];
		for (int i = 1; i < n; i++)
			if (e[i] > mx) mx = e[i];
		return mx;
	}

	public static final double min(double[] e) {
		int n = e.length;
		double mn = e[0];
		for (int i = 1; i < n; i++)
			if (e[i] < mn) mn = e[i];
		return mn;
	}

	public static final int which_max(double[] e) {
		int n = e.length, which = 0;
		double mx = e[0];
		for (int i = 1; i < n; i++)
			if (e[i] > mx) { mx = e[i]; which = i; };
		return which;
	}

	public static final int which_min(double[] e) {
		int n = e.length, which = 0;
		double mn = e[0];
		for (int i = 1; i < n; i++)
			if (e[i] < mn) { mn = e[i]; which = i; };
		return which;
	}

	public static final double[] pmax(double[] a, double[] b) {
		int n = a.length;
		if (n != b.length)
			throw new RuntimeException();
		double[] mx = new double[n];
		for (int i = 0; i < n; i++)
			mx[i] = a[i] > b[i] ? a[i] : b[i];
		return mx;
	}

	public static final double[] pmin(double[] a, double[] b) {
		int n = a.length;
		if (n != b.length)
			throw new RuntimeException();
		double[] mx = new double[n];
		for (int i = 0; i < n; i++)
			mx[i] = a[i] < b[i] ? a[i] : b[i];
		return mx;
	}

	public static final double[] range(double[] e) {
		int n = e.length;
		double mx = e[0], mn = e[0];
		for (int i = 1; i < n; i++) {
			if (e[i] > mx) mx = e[i];
			else if (e[i] < mn) mn = e[i];
		}
		return new double[] { mn, mx };
	}

	public static final double iqr(double[] e) {
		double[] v = quantile0(e, new double[] {0.75, 0.25});
		return v[0] - v[1];
	}

	public static final boolean isEqual(double a, double b, double tol) {
		return (Double.isNaN(a) && Double.isNaN(b)) || (a == b || abs(a - b) <= tol);
	}

	public static final boolean isEqualScaled(double a, double b, double tol) {
		return (Double.isNaN(a) && Double.isNaN(b)) || (a == b || abs(a - b)/(Double.isNaN(a) ? 0 : a) <= tol);
	}

	public static final boolean allEqual(double[] a, double[] b, double tol) {
		int n = a.length;
		if (n != b.length) throw new RuntimeException();
		for (int i = 0; i < n; i++)
			if (!isEqual(a[i], b[i], tol)) return false;
		return true;
	}

	public static final boolean allEqualScaled(double[] a, double[] b, double tol) {
		int n = a.length;
		if (n != b.length) throw new RuntimeException();
		for (int i = 0; i < n; i++)
			if (!isEqualScaled(a[i], b[i], tol)) return false;
		return true;
	}

	public static final boolean isSorted(double[] a, boolean ascending) {
		int n = a.length;
		if (ascending) {
			for (int i = 1; i < n; i++)
				if (a[i-1] > a[i]) return false;
		} else {
			for (int i = 1; i < n; i++)
				if (a[i-1] < a[i]) return false;
		}
		return true;
	}
}

 

Ads help maintain this website.