All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.berkeley.nlp.util.ArrayUtil Maven / Gradle / Ivy

Go to download

The Berkeley parser analyzes the grammatical structure of natural language using probabilistic context-free grammars (PCFGs).

The newest version!
package edu.berkeley.nlp.util;

import java.io.IOException;
import java.text.NumberFormat;
import java.util.Arrays;

import edu.berkeley.nlp.math.SloppyMath;
import edu.berkeley.nlp.util.ListUtils.Generator;

public class ArrayUtil {

	// ARITHMETIC FUNCTIONS

	public static double[] add(double[] a, double c) {
		double[] result = new double[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i] + c;
		}
		return result;
	}

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

	public static int[] add(int[] a, int c) {
		int[] result = new int[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i] + c;
		}
		return result;
	}

	public static float[] add(float[] a, float[] b) {
		float[] result = new float[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i] + b[i];
		}
		return result;
	}

	public static void addInPlace(double[] a, double b) {
		for (int i = 0; i < a.length; i++) {
			a[i] += b;
		}
	}

	public static void addInPlace(double[] a, double[] b) {
		for (int i = 0; i < a.length; i++) {
			a[i] += b[i];
		}
	}

	public static void addInPlace(double[][] a, double[][] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {
			if (a[i] == null || b[i] == null) continue;
			addInPlace(a[i], b[i]);

		}
	}

	public static void addInPlace(double[][][] a, double[][][] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {

			addInPlace(a[i], b[i]);

		}
	}

	public static void addInPlace(double[][][][] a, double[][][][] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {

			addInPlace(a[i], b[i]);

		}
	}

	public static void addInPlace(int[] a, int[] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {
			a[i] += b[i];
		}
	}

	public static void addInPlace(int[][] a, int[][] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {
			addInPlace(a[i], b[i]);
		}
	}

	public static void addInPlace(long[] a, long[] b) {
		if (a == null || b == null) return;
		if (a.length != b.length) return;
		for (int i = 0; i < a.length; ++i) {
			a[i] += b[i];
		}
	}

	public static double approxLogSum(double[] logInputs, int leng) {

		if (leng == 0) {
			throw new IllegalArgumentException();
		}
		int maxIdx = 0;
		double max = logInputs[0];
		for (int i = 1; i < leng; i++) {
			if (logInputs[i] > max) {
				maxIdx = i;
				max = logInputs[i];
			}
		}
		boolean haveTerms = false;
		double intermediate = 0.0;
		double cutoff = max - SloppyMath.LOGTOLERANCE;
		// we avoid rearranging the array and so test indices each time!
		for (int i = 0; i < leng; i++) {
			if (i != maxIdx && logInputs[i] > cutoff) {
				haveTerms = true;
				intermediate += SloppyMath.approxExp(logInputs[i] - max);
			}
		}
		if (haveTerms) {
			return max + SloppyMath.approxLog(1.0 + intermediate);
		} else {
			return max;
		}
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmax(double[] a) {
		double max = Double.NEGATIVE_INFINITY;
		int argmax = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
				argmax = i;
			}
		}
		return argmax;
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmax(float[] a) {
		float max = Float.NEGATIVE_INFINITY;
		int argmax = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
				argmax = i;
			}
		}
		return argmax;
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmax(short[] a) {
		float max = Short.MIN_VALUE;
		int argmax = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
				argmax = i;
			}
		}
		return argmax;
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmin(double[] a) {
		double min = Double.POSITIVE_INFINITY;
		int argmin = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] < min) {
				min = a[i];
				argmin = i;
			}
		}
		return argmin;
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmin(float[] a) {
		float min = Float.POSITIVE_INFINITY;
		int argmin = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] < min) {
				min = a[i];
				argmin = i;
			}
		}
		return argmin;
	}

	/**
	 * @return the index of the max value; if max is a tie, returns the first
	 *         one.
	 */
	public static int argmin(int[] a) {
		int min = Integer.MAX_VALUE;
		int argmin = 0;
		for (int i = 0; i < a.length; i++) {
			if (a[i] < min) {
				min = a[i];
				argmin = i;
			}
		}
		return argmin;
	}

	// CASTS

	public static double average(double[] a) {
		double total = sum(a);
		return total / a.length;
	}

	public static void booleanAndInPlace(boolean[] array, boolean[] other) {
		if (array == null) return;
		for (int i = 0; i < array.length; ++i) {
			array[i] &= other[i];
		}
	}

	public static void booleanAndInPlace(boolean[][] array, boolean[][] other) {
		if (array == null) return;
		for (int i = 0; i < array.length; ++i) {
			booleanAndInPlace(array[i], other[i]);
		}
	}

	public static void booleanAndInPlace(boolean[][][] array, boolean[][][] other) {
		if (array == null) return;
		for (int i = 0; i < array.length; ++i) {
			booleanAndInPlace(array[i], other[i]);
		}
	}

	public static boolean[][] clone(boolean[][] a) {
		boolean[][] res = new boolean[a.length][];
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) res[i] = a[i].clone();
		}
		return res;
	}

	public static boolean[][][] clone(boolean[][][] a) {
		boolean[][][] res = new boolean[a.length][][];
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) res[i] = clone(a[i]);
		}
		return res;
	}

	public static boolean[][][][] clone(boolean[][][][] a) {
		boolean[][][][] res = new boolean[a.length][][][];
		for (int i = 0; i < a.length; i++) {
			res[i] = clone(a[i]);
		}
		return res;
	}

	public static double[][] clone(double[][] a) {
		double[][] res = new double[a.length][];
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) res[i] = a[i].clone();
		}
		return res;
	}

	// LINEAR ALGEBRAIC FUNCTIONS

	public static int[][][] clone(int[][][] a) {
		int[][][] res = new int[a.length][][];
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) res[i] = clone(a[i]);
		}
		return res;
	}
	
	public static double[][][] clone(double[][][] a) {
		double[][][] res = new double[a.length][][];
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) res[i] = clone(a[i]);
		}
		return res;
	}

	public static double[][][][] clone(double[][][][] a) {
		double[][][][] res = new double[a.length][][][];
		for (int i = 0; i < a.length; i++) {
			res[i] = clone(a[i]);
		}
		return res;
	}

	public static int[] clone(int[] original) {
		// TODO Sort out which of these we should use.
		// return Arrays.copyOf(original, original.length);
		// return original.clone(); 
		int[] copy = new int[original.length];
		System.arraycopy(original, 0, copy, 0, original.length);
		return copy;
	}

	public static int[][] clone(int[][] a) {
		int[][] res = new int[a.length][];
		for (int i = 0; i < a.length; i++) {
			if (a[i]!=null) res[i] = clone(a[i]);
		}
		return res;
	}

	public static short[] clone(short[] original) {
		// TODO Sort out which of these we should use.
		// return Arrays.copyOf(original, original.length);
		// return original.clone(); 
		short[] copy = new short[original.length];
		System.arraycopy(original, 0, copy, 0, original.length);
		return copy;
	}
	
	public static double[] clone(double[] original)
	{
		double[] copy = new double[original.length];
		System.arraycopy(original, 0, copy, 0, original.length);
		return copy;
	}

	public static double[] copy(double[] mat) {
		if (mat == null) {
			return null;
		}
		int m = mat.length;
		double[] newMat = new double[m];
		System.arraycopy(mat, 0, newMat, 0, mat.length);
		return newMat;
	}

	public static double[][] copy(double[][] mat) {
		int m = mat.length;
		double[][] newMat = new double[m][];
		for (int r = 0; r < m; r++)
			newMat[r] = copy(mat[r]);
		return newMat;
	}

	public static double[][][] copy(double[][][] mat) {
		int m = mat.length;
		double[][][] newMat = new double[m][][];
		for (int r = 0; r < m; r++)
			newMat[r] = copy(mat[r]);
		return newMat;
	}

	// PRINTING FUNCTIONS

	public static double[][][][] copy(double[][][][] mat) {
		int m = mat.length;
		double[][][][] newMat = new double[m][][][];
		for (int r = 0; r < m; r++)
			newMat[r] = copy(mat[r]);
		return newMat;
	}

	public static float[] doubleArrayToFloatArray(double a[]) {
		float[] result = new float[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = (float) a[i];
		}
		return result;
	}

	public static float[][] doubleArrayToFloatArray(double a[][]) {
		float[][] result = new float[a.length][];
		for (int i = 0; i < a.length; i++) {
			result[i] = new float[a[i].length];
			for (int j = 0; j < a[i].length; j++) {
				result[i][j] = (float) a[i][j];
			}
		}
		return result;
	}

	public static double[] exp(double[] a) {
		double[] result = new double[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = Math.exp(a[i]);
		}
		return result;
	}

	public static void expInPlace(double[] a) {
		for (int i = 0; i < a.length; i++) {
			a[i] = Math.exp(a[i]);
		}
	}

	// SAMPLE ANALYSIS

	public static void fill(boolean[][] a, boolean val) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) Arrays.fill(a[i], val);
		}
	}

	public static void fill(boolean[][] a, int until1, int until2, boolean val) {
		for (int i = 0; i < until1; ++i) {
			Arrays.fill(a[i], 0, until2 == Integer.MAX_VALUE ? a[i].length : until2, val);
		}
	}

	public static void fill(boolean[][][] a, boolean val) {
		for (int i = 0; i < a.length; i++) {
			if (a[i] != null) fill(a[i], val);
		}
	}

	public static void fill(boolean[][][] a, int until, boolean val) {
		for (int i = 0; i < until; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(boolean[][][] a, int until1, int until2, boolean val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, Integer.MAX_VALUE, val);
		}
	}

	public static void fill(boolean[][][] a, int until1, int until2, int until3, boolean val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, val);
		}
	}

	public static void fill(boolean[][][][] a, boolean val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(boolean[][][][] a, int until1, int until2, int until3,
			int until4, boolean val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, until4, val);
		}
	}

	public static void fill(double[][] a, double val) {
		for (int i = 0; i < a.length; i++) {
			Arrays.fill(a[i], val);
		}
	}

	public static void fill(double[][] a, int until1, int until2, double val) {
		for (int i = 0; i < until1; ++i) {
			Arrays.fill(a[i], 0, until2 == Integer.MAX_VALUE ? a[i].length : until2, val);
		}
	}

	public static void fill(double[][][] a, double val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(double[][][] a, int until1, int until2, double val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, Integer.MAX_VALUE, val);
		}
	}

	public static void fill(double[][][] a, int until1, int until2, int until3, double val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, val);
		}
	}

	public static void fill(double[][][][] a, double val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(double[][][][] a, int until1, int until2, int until3,
			int until4, double val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, until4, val);
		}
	}

	public static void fill(double[][][][][] a, double val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(float[][] a, float val) {
		for (int i = 0; i < a.length; i++) {
			Arrays.fill(a[i], val);
		}
	}

	public static void fill(float[][][] a, float val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(float[][][][] a, float val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(float[][][][][] a, float val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(int[][] a, int val) {
		fill(a, a.length, a[0].length, val);
	}

	public static void fill(int[][] a, int until1, int until2, int val) {
		for (int i = 0; i < until1; ++i) {
			Arrays.fill(a[i], 0, until2, val);
		}
	}

	public static void fill(int[][][] a, int until1, int until2, int until3, int val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, val);
		}
	}

	public static void fill(double[][][] a, int until, double val) {
		for (int i = 0; i < until; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(int[][][] a, int until, int val) {
		for (int i = 0; i < until; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(int[][][] a, int val) {
		for (int i = 0; i < a.length; i++) {
			fill(a[i], val);
		}
	}

	public static void fill(int[][][][] a, int until1, int until2, int until3, int until4,
			int val) {
		for (int i = 0; i < until1; i++) {
			fill(a[i], until2, until3, until4, val);
		}
	}

	public static void fill(Object[][] a, int until1, int until2, Object val) {
		for (int i = 0; i < until1; ++i) {
			Arrays.fill(a[i], 0, until2 == Integer.MAX_VALUE ? a[i].length : until2, val);
		}
	}

	public static void fill(Object[][][] a, int until1, int until2, int until3, Object val) {
		for (int i = 0; i < until1; ++i) {
			fill(a[i], until2 == Integer.MAX_VALUE ? a[i].length : until2, until3, val);
		}
	}

	public static void fill(Object[][][][] a, int until1, int until2, int until3,
			int until4, Object val) {
		for (int i = 0; i < until1; ++i) {
			fill(a[i], until2 == Integer.MAX_VALUE ? a[i].length : until2, until3, until4,
					val);
		}
	}

	public static  void fill(T[] array, Generator gen) {
		for (int i = 0; i < array.length; ++i) {
			array[i] = gen.generate(i);
		}
	}

	public static  void fill(T[][] array, Generator gen) {
		for (int i = 0; i < array.length; ++i) {
			ArrayUtil.fill(array[i], gen);
		}
	}

	public static  void fill(T[][][] array, Generator gen) {
		for (int i = 0; i < array.length; ++i) {
			ArrayUtil.fill(array[i], gen);
		}
	}

	public static double[] floatArrayToDoubleArray(float a[]) {
		double[] result = new double[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i];
		}
		return result;
	}

	public static double[][] floatArrayToDoubleArray(float a[][]) {
		double[][] result = new double[a.length][];
		for (int i = 0; i < a.length; i++) {
			result[i] = new double[a[i].length];
			for (int j = 0; j < a[i].length; j++) {
				result[i][j] = a[i][j];
			}
		}
		return result;
	}

	public static boolean hasInfinite(double[] a) {
		for (int i = 0; i < a.length; i++) {
			if (Double.isInfinite(a[i])) return true;
		}
		return false;
	}

	public static boolean hasNaN(double[] a) {
		for (int i = 0; i < a.length; i++) {
			if (Double.isNaN(a[i])) return true;
		}
		return false;
	}

	// UTILITIES

	public static double innerProduct(double[] a, double[] b) {
		double result = 0.0;
		for (int i = 0; i < a.length; i++) {
			result += a[i] * b[i];
		}
		return result;
	}

	public static double innerProduct(float[] a, float[] b) {
		double result = 0.0;
		for (int i = 0; i < a.length; i++) {
			result += a[i] * b[i];
		}
		return result;
	}

	public static double[] inverse(double[] a) {

		double[] retVal = new double[a.length];
		for (int i = 0; i < a.length; ++i) {

			retVal[i] = (a[i] == 0.0) ? 0 : // Double.POSITIVE_INFINITY :
					1.0 / a[i];
		}

		return retVal;
	}

	public static double klDivergence(double[] from, double[] to) {
		double kl = 0.0;
		double tot = sum(from);
		double tot2 = sum(to);
		// System.out.println("tot is " + tot + " tot2 is " + tot2);
		for (int i = 0; i < from.length; i++) {
			if (from[i] == 0.0) {
				continue;
			}
			double num = from[i] / tot;
			double num2 = to[i] / tot2;
			// System.out.println("num is " + num + " num2 is " + num2);
			kl += num * (Math.log(num / num2) / Math.log(2.0));
		}
		return kl;

	}

	public static double[][] load2DMatrixFromFile(String filename) throws IOException {
		String s = StringUtils.slurpFile(filename);
		String[] rows = s.split("[\r\n]+");
		double[][] result = new double[rows.length][];
		for (int i = 0; i < result.length; i++) {
			String[] columns = rows[i].split("\\s+");
			result[i] = new double[columns.length];
			for (int j = 0; j < result[i].length; j++) {
				result[i][j] = Double.parseDouble(columns[j]);
			}
		}
		return result;
	}

	public static double[] log(double[] a) {
		double[] result = new double[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = Math.log(a[i]);
		}
		return result;
	}

	public static void logInPlace(double[] a) {
		for (int i = 0; i < a.length; i++) {
			a[i] = Math.log(a[i]);
		}
	}

	/**
	 * Makes the values in this array sum to 1.0. Does it in place. If the total
	 * is 0.0, sets a to the uniform distribution.
	 */
	public static void logNormalize(double[] a) {
		double logTotal = logSum(a);
		if (logTotal == Double.NEGATIVE_INFINITY) {
			// to avoid NaN values
			double v = -Math.log(a.length);
			for (int i = 0; i < a.length; i++) {
				a[i] = v;
			}
			return;
		}
		shift(a, -logTotal); // subtract log total from each value
	}

	/**
	 * Returns the log of the sum of an array of numbers, which are themselves
	 * input in log form. This is all natural logarithms. Reasonable care is
	 * taken to do this as efficiently as possible (under the assumption that
	 * the numbers might differ greatly in magnitude), with high accuracy, and
	 * without numerical overflow.
	 * 
	 * @param logInputs
	 *            An array of numbers [log(x1), ..., log(xn)]
	 * @return log(x1 + ... + xn)
	 */
	public static double logSum(double[] logInputs) {
		return logSum(logInputs, logInputs.length);
		//    int leng = logInputs.length;
		//    if (leng == 0) {
		//      throw new IllegalArgumentException();
		//    }
		//    int maxIdx = 0;
		//    double max = logInputs[0];
		//    for (int i = 1; i < leng; i++) {
		//      if (logInputs[i] > max) {
		//        maxIdx = i;
		//        max = logInputs[i];
		//      }
		//    }
		//    boolean haveTerms = false;
		//    double intermediate = 0.0;
		//    double cutoff = max - SloppyMath.LOGTOLERANCE;
		//    // we avoid rearranging the array and so test indices each time!
		//    for (int i = 0; i < leng; i++) {
		//      if (i != maxIdx && logInputs[i] > cutoff) {
		//        haveTerms = true;
		//        intermediate += Math.exp(logInputs[i] - max);
		//      }
		//    }
		//    if (haveTerms) {
		//      return max + Math.log(1.0 + intermediate);
		//    } else {
		//      return max;
		//    }
	}

	public static double logSum(double[] logInputs, int leng) {

		if (leng == 0) {
			throw new IllegalArgumentException();
		}
		int maxIdx = 0;
		double max = logInputs[0];
		for (int i = 1; i < leng; i++) {
			if (logInputs[i] > max) {
				maxIdx = i;
				max = logInputs[i];
			}
		}
		boolean haveTerms = false;
		double intermediate = 0.0;
		double cutoff = max - SloppyMath.LOGTOLERANCE;
		// we avoid rearranging the array and so test indices each time!
		for (int i = 0; i < leng; i++) {
			if (i != maxIdx && logInputs[i] > cutoff) {
				haveTerms = true;
				intermediate += Math.exp(logInputs[i] - max);
			}
		}
		if (haveTerms) {
			return max + Math.log(1.0 + intermediate);
		} else {
			return max;
		}
	}

	/**
	 * Returns the log of the sum of an array of numbers, which are themselves
	 * input in log form. This is all natural logarithms. Reasonable care is
	 * taken to do this as efficiently as possible (under the assumption that
	 * the numbers might differ greatly in magnitude), with high accuracy, and
	 * without numerical overflow.
	 * 
	 * @param logInputs
	 *            An array of numbers [log(x1), ..., log(xn)]
	 * @return log(x1 + ... + xn)
	 */
	public static float logSum(float[] logInputs) {
		int leng = logInputs.length;
		if (leng == 0) {
			throw new IllegalArgumentException();
		}
		int maxIdx = 0;
		float max = logInputs[0];
		for (int i = 1; i < leng; i++) {
			if (logInputs[i] > max) {
				maxIdx = i;
				max = logInputs[i];
			}
		}
		boolean haveTerms = false;
		double intermediate = 0.0f;
		float cutoff = (float) (max - SloppyMath.LOGTOLERANCE);
		// we avoid rearranging the array and so test indices each time!
		for (int i = 0; i < leng; i++) {
			if (i != maxIdx && logInputs[i] > cutoff) {
				haveTerms = true;
				intermediate += Math.exp(logInputs[i] - max);
			}
		}
		if (haveTerms) {
			return max + (float) Math.log(1.0 + intermediate);
		} else {
			return max;
		}
	}

	public static double max(double[] a) {
		return a[argmax(a)];
	}

	public static float max(float[] a) {
		return a[argmax(a)];
	}

	public static float max(short[] a) {
		return a[argmax(a)];
	}

	public static int max(int[] a) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
			}
		}
		return max;
	}

	public static int max(Integer[] a) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < a.length; i++) {
			if (a[i] > max) {
				max = a[i];
			}
		}
		return max;
	}

	public static double mean(double[] a) {
		return sum(a) / a.length;
	}

	public static double min(double[] a) {
		return a[argmin(a)];
	}

	public static float min(float[] a) {
		return a[argmin(a)];
	}

	public static int min(int[] a) {
		return a[argmin(a)];
	}

	/**
	 * Scales the values in this array by c.
	 */
	public static double[] multiply(double[] a, double c) {
		double[] result = new double[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i] * c;
		}
		return result;
	}

	/**
	 * Scales the values in this array by c.
	 */
	public static double[][] multiply(double[][] a, double c) {
		double[][] result = new double[a.length][a[0].length];
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a[0].length; j++) {
				result[i][j] = a[i][j] * c;
			}
		}
		return result;
	}

	/**
	 * Scales the values in this array by c.
	 */
	public static float[] multiply(float[] a, float c) {
		float[] result = new float[a.length];
		for (int i = 0; i < a.length; i++) {
			result[i] = a[i] * c;
		}
		return result;
	}

	/**
	 * Scales in place the values in this array by c.
	 */
	public static void multiplyInPlace(double[] a, double c) {
		for (int i = 0; i < a.length; i++) {
			a[i] = a[i] * c;
		}
	}

	/**
	 * Computes 2-norm of vector
	 * 
	 * @param a
	 * @return Euclidean norm of a
	 */
	public static double norm(double[] a) {
		double squaredSum = 0;
		for (int i = 0; i < a.length; i++) {
			squaredSum += a[i] * a[i];
		}
		return Math.sqrt(squaredSum);
	}

	// PRINTING FUNCTIONS

	/**
	 * Computes 2-norm of vector
	 * 
	 * @param a
	 * @return Euclidean norm of a
	 */
	public static double norm(float[] a) {
		double squaredSum = 0;
		for (int i = 0; i < a.length; i++) {
			squaredSum += a[i] * a[i];
		}
		return Math.sqrt(squaredSum);
	}

	/**
	 * Computes 1-norm of vector
	 * 
	 * @param a
	 * @return 1-norm of a
	 */
	public static double norm_1(double[] a) {
		double sum = 0;
		for (int i = 0; i < a.length; i++) {
			sum += (a[i] < 0 ? -a[i] : a[i]);
		}
		return sum;
	}

	/**
	 * Computes 1-norm of vector
	 * 
	 * @param a
	 * @return 1-norm of a
	 */
	public static double norm_1(float[] a) {
		double sum = 0;
		for (int i = 0; i < a.length; i++) {
			sum += (a[i] < 0 ? -a[i] : a[i]);
		}
		return sum;
	}

	/**
	 * Computes inf-norm of vector
	 * 
	 * @param a
	 * @return inf-norm of a
	 */
	public static double norm_inf(double[] a) {
		double max = Double.NEGATIVE_INFINITY;
		for (int i = 0; i < a.length; i++) {
			if (Math.abs(a[i]) > max) {
				max = Math.abs(a[i]);
			}
		}
		return max;
	}

	/**
	 * Computes inf-norm of vector
	 * 
	 * @param a
	 * @return inf-norm of a
	 */
	public static double norm_inf(float[] a) {
		double max = Double.NEGATIVE_INFINITY;
		for (int i = 0; i < a.length; i++) {
			if (Math.abs(a[i]) > max) {
				max = Math.abs(a[i]);
			}
		}
		return max;
	}

	/**
	 * Makes the values in this array sum to 1.0. Does it in place. If the total
	 * is 0.0, sets a to the uniform distribution.
	 */
	public static void normalize(double[] a) {
		double total = sum(a);
		if (total == 0.0) {
			throw new RuntimeException("Can't normalize an array with sum 0.0");
		}
		scale(a, 1.0 / total); // divide each value by total
	}

	public static void normalize(double[][] a) {
		double total = sum(a);
		if (total == 0.0) { throw new RuntimeException("Can't normalize an array with sum 0.0"); }
		for (int i=0; i T[] reallocArray(T[] array, int minLength, Class klass,
			Generator gen) {
		if (array == null || array.length < minLength) {
			array = ListUtils.newArray(minLength, klass, gen);
		}

		fill(array, gen);

		return array;

	}

	public static  T[][] reallocArray(T[][] array, int minLength1, final int minLength2,
			final Class klass, final Generator gen) {

		if (array == null || array.length < minLength1 || array[0].length < minLength2) {
			array = ListUtils.newArray(minLength1, ListUtils.newArray(minLength2, klass,
					gen));
		}

		fill(array, new Generator() {

			public T[] generate(int i) {
				return ListUtils.newArray(minLength2, klass, gen);
			}

		});

		return array;

	}

	/**
	 * Scales the values in this array by b. Does it in place.
	 */
	public static void scale(double[] a, double b) {
		for (int i = 0; i < a.length; i++) {
			a[i] = a[i] * b;
		}
	}

	/**
	 * Scales the values in this array by b. Does it in place.
	 */
	public static void scale(float[] a, double b) {
		for (int i = 0; i < a.length; i++) {
			a[i] = (float) (a[i] * b);
		}
	}

	public static void setToLogDeterministic(double[] a, int i) {
		for (int j = 0; j < a.length; j++) {
			if (j == i) {
				a[j] = 0.0;
			} else {
				a[j] = Double.NEGATIVE_INFINITY;
			}
		}
	}

	public static void setToLogDeterministic(float[] a, int i) {
		for (int j = 0; j < a.length; j++) {
			if (j == i) {
				a[j] = 0.0F;
			} else {
				a[j] = Float.NEGATIVE_INFINITY;
			}
		}
	}

	/**
	 * Shifts the values in this array by b. Does it in place.
	 */
	public static void shift(double[] a, double b) {
		for (int i = 0; i < a.length; i++) {
			a[i] = a[i] + b;
		}
	}

	public static double standardErrorOfMean(double[] a) {
		return stdev(a) / Math.sqrt(a.length);
	}

	public static double stdev(double[] a) {
		return Math.sqrt(variance(a));
	}

	public static int[] subArray(int[] a, int from, int to) {
		int[] result = new int[to - from];
		System.arraycopy(a, from, result, 0, to - from);
		return result;
	}

	public static double[] subArray(double[] a, int from, int to) {
		double[] result = new double[to - from];
		System.arraycopy(a, from, result, 0, to - from);
		return result;
	}

	public static double[][] subMatrix(double[][] ds, int i, int ni, int j, int nj) {
		double[][] retVal = new double[ni][nj];
		for (int k = i; k < i + ni; ++k) {
			for (int l = j; l < j + nj; ++l) {
				retVal[k - i][l - j] = ds[k][l];
			}
		}
		return retVal;
	}

	public static double[] subtract(double[] a, double[] b) {
		double[] c = new double[a.length];

		for (int i = 0; i < a.length; i++) {
			c[i] = a[i] - b[i];
		}
		return c;
	}

	public static void subtract(double[] a, double[] b, double[] scratch) {
		assert b != null;
		assert a.length == b.length;
		for (int i = 0; i < a.length; ++i) {
			scratch[i] = a[i] - b[i];
		}
	}

	public static void multiply(double[] a, double b, double[] scratch) {
		assert a != null;
		for (int i = 0; i < a.length; ++i) {
			scratch[i] = a[i] * b;
		}
	}

	public static float[] subtract(float[] a, float[] b) {
		float[] c = new float[a.length];

		for (int i = 0; i < a.length; i++) {
			c[i] = a[i] - b[i];
		}
		return c;
	}

	public static double sum(double[] a) {
		if (a == null) {
			return 0.0;
		}
		double result = 0.0;
		for (int i = 0; i < a.length; i++) {
			result += a[i];
		}
		return result;
	}
	
	public static double sum(double[][] a)
	{
		if (a == null) {
			return 0.0;
		}
		double result = 0.0;
		for (int i=0; i cellSize - 1) {
					s = s.substring(0, cellSize - 1);
				}
				s = StringUtils.padLeft(s, cellSize);
				result.append(s);
			}
			if (printTotals) {
				result.append(StringUtils.padLeft("Total", cellSize));
			}
			result.append("\n\n");
		}
		for (int i = 0; i < counts.length; i++) {
			// row label
			if (rowLabels != null) {
				String s = rowLabels[i].toString();
				s = StringUtils.pad(s, cellSize); // left align this guy only
				result.append(s);
			}
			// value
			for (int j = 0; j < counts[i].length; j++) {
				result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
			}
			// the row total
			if (printTotals) {
				result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
			}
			result.append("\n");
		}
		result.append("\n");
		// the col totals
		if (printTotals) {
			result.append(StringUtils.pad("Total", cellSize));
			for (int j = 0; j < colTotals.length; j++) {
				result.append(StringUtils.padLeft(nf.format(colTotals[j]), cellSize));
			}
			result.append(StringUtils.padLeft(nf.format(total), cellSize));
		}
		result.append("\n");
		return result.toString();
	}

	public static String toString(double[][][] a) {
		String s = "[";
		for (int i = 0; i < a.length; i++) {
			s = s.concat(toString(a[i]) + ", ");
		}
		return s + "]";
	}

	public static String toString(float[] a) {
		return toString(a, null);
	}

	public static String toString(float[] a, NumberFormat nf) {
		if (a == null) return null;
		if (a.length == 0) return "[]";
		StringBuffer b = new StringBuffer();
		b.append("[");
		for (int i = 0; i < a.length - 1; i++) {
			String s;
			if (nf == null) {
				s = String.valueOf(a[i]);
			} else {
				s = nf.format(a[i]);
			}
			b.append(s);
			b.append(", ");
		}
		String s;
		if (nf == null) {
			s = String.valueOf(a[a.length - 1]);
		} else {
			s = nf.format(a[a.length - 1]);
		}
		b.append(s);
		b.append(']');
		return b.toString();
	}

	public static String toString(float[][] counts) {
		return toString(counts, 10, null, null, NumberFormat.getIntegerInstance(), false);
	}

	// CASTS

	public static String toString(float[][] counts, int cellSize, Object[] rowLabels,
			Object[] colLabels, NumberFormat nf, boolean printTotals) {
		// first compute row totals and column totals
		double[] rowTotals = new double[counts.length];
		double[] colTotals = new double[counts[0].length]; // assume it's square
		double total = 0.0;
		for (int i = 0; i < counts.length; i++) {
			for (int j = 0; j < counts[i].length; j++) {
				rowTotals[i] += counts[i][j];
				colTotals[j] += counts[i][j];
				total += counts[i][j];
			}
		}
		StringBuffer result = new StringBuffer();
		// column labels
		if (colLabels != null) {
			result.append(StringUtils.padLeft("", cellSize));
			for (int j = 0; j < counts[0].length; j++) {
				String s = colLabels[j].toString();
				if (s.length() > cellSize - 1) {
					s = s.substring(0, cellSize - 1);
				}
				s = StringUtils.padLeft(s, cellSize);
				result.append(s);
			}
			if (printTotals) {
				result.append(StringUtils.padLeft("Total", cellSize));
			}
			result.append("\n\n");
		}
		for (int i = 0; i < counts.length; i++) {
			// row label
			if (rowLabels != null) {
				String s = rowLabels[i].toString();
				s = StringUtils.pad(s, cellSize); // left align this guy only
				result.append(s);
			}
			// value
			for (int j = 0; j < counts[i].length; j++) {
				result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
			}
			// the row total
			if (printTotals) {
				result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
			}
			result.append("\n");
		}
		result.append("\n");
		// the col totals
		if (printTotals) {
			result.append(StringUtils.pad("Total", cellSize));
			for (int j = 0; j < colTotals.length; j++) {
				result.append(StringUtils.padLeft(nf.format(colTotals[j]), cellSize));
			}
			result.append(StringUtils.padLeft(nf.format(total), cellSize));
		}
		result.append("\n");
		return result.toString();
	}

	public static String toString(float[][][] a) {
		String s = "[";
		for (int i = 0; i < a.length; i++) {
			s = s.concat(toString(a[i]) + ", ");
		}
		return s + "]";
	}

	public static String toString(int[] a) {
		return toString(a, null);
	}

	public static String toString(int[] a, NumberFormat nf) {
		if (a == null) return null;
		if (a.length == 0) return "[]";
		StringBuffer b = new StringBuffer();
		b.append("[");
		for (int i = 0; i < a.length - 1; i++) {
			String s;
			if (nf == null) {
				s = String.valueOf(a[i]);
			} else {
				s = nf.format(a[i]);
			}
			b.append(s);
			b.append(", ");
		}
		String s;
		if (nf == null) {
			s = String.valueOf(a[a.length - 1]);
		} else {
			s = nf.format(a[a.length - 1]);
		}
		b.append(s);
		b.append(']');
		return b.toString();
	}

	// ARITHMETIC FUNCTIONS

	public static String toString(int[][] counts) {
		return toString(counts, 10, null, null, NumberFormat.getInstance(), false);
	}

	public static String toString(int[][] counts, int cellSize, Object[] rowLabels,
			Object[] colLabels, NumberFormat nf, boolean printTotals) {
		// first compute row totals and column totals
		int[] rowTotals = new int[counts.length];
		int[] colTotals = new int[counts[0].length]; // assume it's square
		int total = 0;
		for (int i = 0; i < counts.length; i++) {
			for (int j = 0; j < counts[i].length; j++) {
				rowTotals[i] += counts[i][j];
				colTotals[j] += counts[i][j];
				total += counts[i][j];
			}
		}
		StringBuffer result = new StringBuffer();
		// column labels
		if (colLabels != null) {
			result.append(StringUtils.padLeft("", cellSize));
			for (int j = 0; j < counts[0].length; j++) {
				String s = colLabels[j].toString();
				if (s.length() > cellSize - 1) {
					s = s.substring(0, cellSize - 1);
				}
				s = StringUtils.padLeft(s, cellSize);
				result.append(s);
			}
			if (printTotals) {
				result.append(StringUtils.padLeft("Total", cellSize));
			}
			result.append("\n\n");
		}
		for (int i = 0; i < counts.length; i++) {
			// row label
			if (rowLabels != null) {
				String s = rowLabels[i].toString();
				s = StringUtils.padOrTrim(s, cellSize); // left align this guy only
				result.append(s);
			}
			// value
			for (int j = 0; j < counts[i].length; j++) {
				result.append(StringUtils.padLeft(nf.format(counts[i][j]), cellSize));
			}
			// the row total
			if (printTotals) {
				result.append(StringUtils.padLeft(nf.format(rowTotals[i]), cellSize));
			}
			result.append("\n");
		}
		result.append("\n");
		// the col totals
		if (printTotals) {
			result.append(StringUtils.pad("Total", cellSize));
			for (int j = 0; j < colTotals.length; j++) {
				result.append(StringUtils.padLeft(nf.format(colTotals[j]), cellSize));
			}
			result.append(StringUtils.padLeft(nf.format(total), cellSize));
		}
		result.append("\n");
		return result.toString();
	}

	public static double variance(double[] a) {
		return sumSquaredError(a) / (a.length - 1);
	}

	private static void printMatrix(double[][] a) {
		final int len = 5;
		for (int i = 0; i < len; ++i) {
			System.out.print("[");
			for (int j = 0; j < len; ++j) {
				System.out.print(a[i][j] + "\t,");
			}
			System.out.println("]");
		}
	}

	public static  boolean hasNull(T[] array) {
		for (T t : array) {
			if (t == null) return true;
		}
		return false;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy