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 <T> void fill(T[] array, Generator<T> gen) {
for (int i = 0; i < array.length; ++i) {
array[i] = gen.generate(i);
}
}
public static <T> void fill(T[][] array, Generator<T> gen) {
for (int i = 0; i < array.length; ++i) {
ArrayUtil.fill(array[i], gen);
}
}
public static <T> void fill(T[][][] array, Generator<T> 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<a.length; i++) {
scale(a[i], 1.0 / total); // divide each value by total
}
}
/**
* 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(float[] a) {
float total = sum(a);
if (total == 0.0) {
throw new RuntimeException("Can't normalize an array with sum 0.0");
}
scale(a, 1.0F / total); // divide each value by total
}
public static double[][] outerProduct(double[] a, double[] b) {
if (a.length != b.length) {
return null;
}
double[][] retVal = new double[a.length][a.length];
for (int i = 0; i < a.length; ++i) {
for (int j = 0; j < a.length; ++j) {
retVal[i][j] = a[i] * b[j];
}
}
return retVal;
}
public static double[] pairwiseAdd(double[] a, double[] b) {
if (a.length != b.length) {
throw new RuntimeException();
}
double[] result = new double[a.length];
for (int i = 0; i < result.length; i++) {
result[i] = a[i] + b[i];
}
return result;
}
/**
* Assumes that both arrays have same length.
*/
public static double[] pairwiseMultiply(double[] a, double[] b) {
if (a.length != b.length) {
throw new RuntimeException();
}
double[] result = new double[a.length];
for (int i = 0; i < result.length; i++) {
result[i] = a[i] * b[i];
}
return result;
}
/**
* Puts the result in the result array. Assumes that all arrays have same
* length.
*/
public static void pairwiseMultiply(double[] a, double[] b, double[] result) {
if (a.length != b.length) {
throw new RuntimeException();
}
for (int i = 0; i < result.length; i++) {
result[i] = a[i] * b[i];
}
}
/**
* Assumes that both arrays have same length.
*/
public static float[] pairwiseMultiply(float[] a, float[] b) {
if (a.length != b.length) {
throw new RuntimeException();
}
float[] result = new float[a.length];
for (int i = 0; i < result.length; i++) {
result[i] = a[i] * b[i];
}
return result;
}
/**
* Puts the result in the result array. Assumes that all arrays have same
* length.
*/
public static void pairwiseMultiply(float[] a, float[] b, float[] result) {
if (a.length != b.length) {
throw new RuntimeException();
}
for (int i = 0; i < result.length; i++) {
result[i] = a[i] * b[i];
}
}
/**
* Scales the values in this array by c.
*/
public static double[] pow(double[] a, double c) {
double[] result = new double[a.length];
for (int i = 0; i < a.length; i++) {
result[i] = Math.pow(a[i], c);
}
return result;
}
/**
* Scales the values in this array by c.
*/
public static float[] pow(float[] a, float c) {
float[] result = new float[a.length];
for (int i = 0; i < a.length; i++) {
result[i] = (float) Math.pow(a[i], c);
}
return result;
}
/**
* Scales the values in this array by c.
*/
public static void powInPlace(double[] a, double c) {
for (int i = 0; i < a.length; i++) {
a[i] = Math.pow(a[i], c);
}
}
/**
* Scales the values in this array by c.
*/
public static void powInPlace(float[] a, float c) {
for (int i = 0; i < a.length; i++) {
a[i] = (float) Math.pow(a[i], c);
}
}
public static double product(double[] a) {
double retVal = 1.0;
for (double d : a) {
retVal *= d;
}
return retVal;
}
public static boolean[] reallocArray(boolean[] array, int minLength) {
if (array == null || array.length < minLength) {
return new boolean[minLength];
}
return array;
}
public static boolean[] reallocArray(boolean[] array, int minLength, boolean fillVal) {
boolean[] newArray = reallocArray(array, minLength);
Arrays.fill(newArray, fillVal);
return newArray;
}
public static boolean[][] reallocArray(boolean[][] array, int minLength1, int minLength2) {
if (array == null || array.length < minLength1) {
return new boolean[minLength1][minLength2];
}
return array;
}
public static boolean[][] reallocArray(boolean[][] array, int minLength1,
int minLength2, boolean fillVal) {
boolean[][] newArray = reallocArray(array, minLength1, minLength2);
ArrayUtil.fill(newArray, minLength1, minLength2, fillVal);
return newArray;
}
public static boolean[][][] reallocArray(boolean[][][] array, int minLength1,
int minLength2, int minLength3) {
if (array == null || array.length < minLength1) {
return new boolean[minLength1][minLength2][minLength3];
}
return array;
}
public static boolean[][][] reallocArray(boolean[][][] array, int minLength1,
int minLength2, int minLength3, boolean fillVal) {
boolean[][][] newArray = reallocArray(array, minLength1, minLength2, minLength3);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, fillVal);
return newArray;
}
public static boolean[][][][] reallocArray(boolean[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4) {
if (array == null || array.length < minLength1 || array[0].length < minLength2
|| array[0][0].length < minLength3 || array[0][0][0].length < minLength4) {
return new boolean[minLength1][minLength2][minLength3][minLength4];
}
return array;
}
public static boolean[][][][] reallocArray(boolean[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4, boolean fillVal) {
boolean[][][][] newArray = reallocArray(array, minLength1, minLength2, minLength3,
minLength4);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, minLength4, fillVal);
return newArray;
}
/**
* If array is less than the minimum length (or null), a new array is
* allocated with length minLength; Otherwise, the argument is returned
*
* @param array
* @param minLength
* @return
*/
public static double[] reallocArray(double[] array, int minLength) {
if (array == null || array.length < minLength) {
return new double[minLength];
}
return array;
}
public static double[] reallocArray(double[] array, int minLength, double fillVal) {
double[] newArray = reallocArray(array, minLength);
Arrays.fill(newArray, fillVal);
return newArray;
}
public static double[][] reallocArray(double[][] array, int minLength1, int minLength2) {
if (array == null || array.length < minLength1) {
return new double[minLength1][minLength2];
}
return array;
}
public static double[][] reallocArray(double[][] array, int minLength1, int minLength2,
double fillVal) {
double[][] newArray = reallocArray(array, minLength1, minLength2);
ArrayUtil.fill(newArray, minLength1, minLength2, fillVal);
return newArray;
}
public static double[][][] reallocArray(double[][][] array, int minLength1,
int minLength2, int minLength3) {
if (array == null || array.length < minLength1) {
return new double[minLength1][minLength2][minLength3];
}
return array;
}
public static double[][][] reallocArray(double[][][] array, int minLength1,
int minLength2, int minLength3, double fillVal) {
double[][][] newArray = reallocArray(array, minLength1, minLength2, minLength3);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, fillVal);
return newArray;
}
public static double[][][][] reallocArray(double[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4) {
if (array == null || array.length < minLength1 || array[0].length < minLength2
|| array[0][0].length < minLength3 || array[0][0][0].length < minLength4) {
return new double[minLength1][minLength2][minLength3][minLength4];
}
return array;
}
public static double[][][][] reallocArray(double[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4, double fillVal) {
double[][][][] newArray = reallocArray(array, minLength1, minLength2, minLength3,
minLength4);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, minLength4, fillVal);
return newArray;
}
public static int[] reallocArray(int[] array, int minLength) {
if (array == null || array.length < minLength) {
return new int[minLength];
}
return array;
}
public static int[] reallocArray(int[] array, int minLength, int fillVal) {
int[] newArray = reallocArray(array, minLength);
Arrays.fill(newArray, fillVal);
return newArray;
}
public static int[][] reallocArray(int[][] array, int minLength1, int minLength2) {
if (array == null || array.length < minLength1) {
return new int[minLength1][minLength2];
}
return array;
}
public static int[][] reallocArray(int[][] array, int minLength1, int minLength2,
int fillVal) {
int[][] newArray = reallocArray(array, minLength1, minLength2);
ArrayUtil.fill(newArray, minLength1, minLength2, fillVal);
return newArray;
}
public static int[][][] reallocArray(int[][][] array, int minLength1, int minLength2,
int minLength3) {
if (array == null || array.length < minLength1) {
return new int[minLength1][minLength2][minLength3];
}
return array;
}
public static int[][][] reallocArray(int[][][] array, int minLength1, int minLength2,
int minLength3, int fillVal) {
int[][][] newArray = reallocArray(array, minLength1, minLength2, minLength3);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, fillVal);
return newArray;
}
public static int[][][][] reallocArray(int[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4) {
if (array == null || array.length < minLength1 || array[0].length < minLength2
|| array[0][0].length < minLength3 || array[0][0][0].length < minLength4) {
return new int[minLength1][minLength2][minLength3][minLength4];
}
return array;
}
public static int[][][][] reallocArray(int[][][][] array, int minLength1,
int minLength2, int minLength3, int minLength4, int fillVal) {
int[][][][] newArray = reallocArray(array, minLength1, minLength2, minLength3,
minLength4);
ArrayUtil.fill(newArray, minLength1, minLength2, minLength3, minLength4, fillVal);
return newArray;
}
public static <T> T[] reallocArray(T[] array, int minLength, Class<T> klass,
Generator<T> gen) {
if (array == null || array.length < minLength) {
array = ListUtils.newArray(minLength, klass, gen);
}
fill(array, gen);
return array;
}
public static <T> T[][] reallocArray(T[][] array, int minLength1, final int minLength2,
final Class<T> klass, final Generator<T> gen) {
if (array == null || array.length < minLength1 || array[0].length < minLength2) {
array = ListUtils.newArray(minLength1, ListUtils.newArray(minLength2, klass,
gen));
}
fill(array, new Generator<T[]>() {
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<a.length; i++)
{
result += sum(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<a.length; i++)
{
result += sum(a[i]);
}
return result;
}
public static double sum(double[] a, int len) {
double result = 0.0;
for (int i = 0; i < len; i++) {
result += a[i];
}
return result;
}
public static float sum(float[] a) {
float result = 0.0F;
for (int i = 0; i < a.length; i++) {
result += a[i];
}
return result;
}
public static int sum(int[] a) {
int result = 0;
for (int i = 0; i < a.length; i++) {
result += a[i];
}
return result;
}
public static long sum(long[] a) {
int result = 0;
for (int i = 0; i < a.length; i++) {
result += a[i];
}
return result;
}
public static double sumSquaredError(double[] a) {
double mean = mean(a);
double result = 0.0;
for (int i = 0; i < a.length; i++) {
double diff = a[i] - mean;
result += (diff * diff);
}
return result;
}
public static String toString(boolean[][] a) {
String s = "[";
for (int i = 0; i < a.length; i++) {
s = s.concat(Arrays.toString(a[i]) + ", ");
}
return s + "]";
}
public static String toString(byte[] a) {
return toString(a, null);
}
public static String toString(byte[] 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(double[] a) {
return toString(a, null);
}
public static String toString(double[] 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(double[][] counts) {
return toString(counts, 10, null, null, NumberFormat.getInstance(), false);
}
public static String toString(double[][] counts, int cellSize, Object[] rowLabels,
Object[] colLabels, NumberFormat nf, boolean printTotals) {
if (counts == null) return null;
// 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(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 <T> boolean hasNull(T[] array) {
for (T t : array) {
if (t == null) return true;
}
return false;
}
}