package edu.berkeley.nlp.math; import java.util.Arrays; /** */ public class DoubleArrays { public static double[] clone(double[] x) { double[] y = new double[x.length]; assign(y, x); return y; } public static void assign(double[] y, double[] x) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); System.arraycopy(x, 0, y, 0, x.length); } public static double innerProduct(double[] x, double[] y) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double result = 0.0; for (int i = 0; i < x.length; i++) { result += x[i] * y[i]; } return result; } public static double innerProduct(Double[] x, double[] y) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double result = 0.0; for (int i = 0; i < x.length; i++) { result += x[i] * y[i]; } return result; } public static double[] addMultiples(double[] x, double xMultiplier, double[] y, double yMuliplier) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double[] z = new double[x.length]; for (int i = 0; i < z.length; i++) { z[i] = x[i] * xMultiplier + y[i] * yMuliplier; } return z; } public static double[] constantArray(double c, int length) { double[] x = new double[length]; Arrays.fill(x, c); return x; } public static double[] pointwiseMultiply(double[] x, double[] y) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double[] z = new double[x.length]; for (int i = 0; i < z.length; i++) { z[i] = x[i] * y[i]; } return z; } public static boolean probabilisticNormalize(double[] x) { double sum = add(x); if (sum <= 0.0) return false; scale(x,1.0/sum); return true; } public static String toString(double[] x) { return toString(x, x.length); } public static String toString(double[][] x) { StringBuilder sb = new StringBuilder(); for (double[] row: x) { sb.append(DoubleArrays.toString(row)); sb.append("\n"); } return sb.toString(); } public static String toString(double[] x, int length) { StringBuffer sb = new StringBuffer(); sb.append("["); for (int i = 0; i < SloppyMath.min(x.length, length); i++) { sb.append(String.format("%.5f",x[i])); if (i + 1 < SloppyMath.min(x.length, length)) sb.append(", "); } sb.append("]"); return sb.toString(); } public static void scale(double[] x, double s) { if (s == 1.0) return; for (int i = 0; i < x.length; i++) { x[i] *= s; } } public static double[] multiply(double[] x, double s) { double[] result = new double[x.length]; if (s == 1.0) { System.arraycopy(x, 0, result, 0, x.length); return result; } for (int i = 0; i < x.length; i++) { result[i] = x[i] * s; } return result; } public static int argMax(double[] v) { int maxI = -1; double maxV = Double.NEGATIVE_INFINITY; for (int i = 0; i < v.length; i++) { if (v[i] > maxV) { maxV = v[i]; maxI = i; } } return maxI; } public static double max(double[] v) { double maxV = Double.NEGATIVE_INFINITY; for (int i = 0; i < v.length; i++) { if (v[i] > maxV) { maxV = v[i]; } } return maxV; } public static double max(double[][] m) { double max = Double.NEGATIVE_INFINITY; for (double[] row : m) { max = Math.max(max(row),max); } return max; } public static int argMin(double[] v) { int minI = -1; double minV = Double.POSITIVE_INFINITY; for (int i = 0; i < v.length; i++) { if (v[i] < minV) { minV = v[i]; minI = i; } } return minI; } public static double min(double[] v) { double minV = Double.POSITIVE_INFINITY; for (int i = 0; i < v.length; i++) { if (v[i] < minV) { minV = v[i]; } } return minV; } public static double min(double[][] m) { double min = Double.POSITIVE_INFINITY; for (double[] row : m) { min = Math.min(min(row),min); } return min; } public static double maxAbs(double[] v) { double maxV = 0; for (int i = 0; i < v.length; i++) { double abs = (v[i] <= 0.0d) ? 0.0d - v[i] : v[i]; if (abs > maxV) { maxV = abs; } } return maxV; } public static double[] add(double[] a, double b) { double[] result = new double[a.length]; for (int i = 0; i < a.length; i++) { double v = a[i]; result[i] = v + b; } return result; } public static double add(double[] a) { double sum = 0.0; for (int i = 0; i < a.length; i++) { sum += a[i]; } return sum; } public static int add(int[] a) { int sum = 0; for (int i = 0; i < a.length; i++) { sum += a[i]; } return sum; } public static double add(double[] a, int first, int last) { if (last >= a.length) throw new RuntimeException("last beyond end of array"); if (first < 0) throw new RuntimeException("first must be at least 0"); double sum = 0.0; for (int i = first; i <= last; i++) { sum += a[i]; } return sum; } public static double vectorLength(double[] x) { return Math.sqrt(innerProduct(x, x)); } public static double[] add(double[] x, double[] y) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double[] result = new double[x.length]; for (int i = 0; i < x.length; i++) { result[i] = x[i] + y[i]; } return result; } public static void subtractInPlace(double[] x, double[] y) { // be in cvs for (int i=0; i < x.length; ++i) { x[i] -= y[i]; } } /** * If a subtraction results in NaN (i.e -inf - (-inf)) * does not perform the computation. * @param x * @param y */ public static void subtractInPlaceUnsafe(double[] x, double[] y) { // be in cvs for (int i=0; i < x.length; ++i) { if (Double.isNaN(x[i]-y[i])) { continue; } x[i] -= y[i]; } } public static double[] subtract(double[] x, double[] y) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); double[] result = new double[x.length]; for (int i = 0; i < x.length; i++) { result[i] = x[i] - y[i]; } return result; } public static double[] exponentiate(double[] pUnexponentiated) { double[] exponentiated = new double[pUnexponentiated.length]; for (int index = 0; index < pUnexponentiated.length; index++) { exponentiated[index] = SloppyMath.exp(pUnexponentiated[index]); } return exponentiated; } public static double[][] exponentiate(double[][] pUnexponentiated) { double[][] exponentiated = new double[pUnexponentiated.length][]; for (int index = 0; index < pUnexponentiated.length; index++) { exponentiated[index] = exponentiate(pUnexponentiated[index]); } return exponentiated; } public static void truncate(double[] x, double maxVal) { for (int index = 0; index < x.length; index++) { if (x[index] > maxVal) x[index] = maxVal; else if (x[index] < -maxVal) x[index] = -maxVal; } } public static void initialize(double[] x, double d) { Arrays.fill(x, d); } public static void initialize(Object[] x, double d) { for (int i = 0; i < x.length; i++) { Object o = x[i]; if (o instanceof double[]) initialize((double[]) o, d); else initialize((Object[]) o, d); } } public static void addInPlace(double[] x, double c) { for (int i = 0; i < x.length; i++) { x[i] += c; } } public static void addInPlace(double[] x, double[] y) { assert y.length >= x.length; for (int i = 0; i < x.length; ++i) { x[i] += y[i]; } } public static void addInPlace2D(double[][] x, double[][] y) { // TODO Auto-generated method stub assert y.length >= x.length; for (int i = 0; i < x.length; ++i) { DoubleArrays.addInPlace(x[i], y[i]); } } public static void multiplyInPlace(double[] x, double[] y) { for (int i = 0; i < x.length; i++) { x[i] *= y[i]; } } public static double[] average(double[][] x) { if (x.length == 0) { return null; } double[] sum = x[0]; for (int i = 1; i < x.length; i++) { sum = add(sum, x[i]); } double[] avg = multiply(sum, (1.0 / x.length)); return avg; } /* * project x onto a orthant defined by y */ public static void project(double[] x, double[] y){ for (int i=0; i<x.length; i++){ if (x[i]*y[i] <= 0) x[i] = 0; } } /* * project x onto a orthant defined by y */ public static void project2(double[] x, double[] y){ for (int i=0; i<x.length; i++){ if (x[i]*y[i] < 0) x[i] = 0; } } public static void checkNonNegative(double[] x) { for (double v : x) { if (v < -1.0e-10) { throw new RuntimeException("Negative number " + v); } } } public static void checkNonNegative(double[][] m) { for (double[] row : m) { checkNonNegative(row); } } /** * Loop and ensure all elements are non-infiite * and non-nan, throws an exception if one is * @param x */ public static void checkValid(double[] x) { for (double v : x) { if (Double.isNaN(v)) { throw new RuntimeException("Invalid entry " + v); } } } public static void checkValid(double[][] m) { for (double[] row : m) { checkValid(row); } } public static double lInfinityDist(double[] x, double[] y) { double max = Double.NEGATIVE_INFINITY; for (int i = 0; i < x.length; i++) { max = Math.max(max,Math.abs(x[i]-y[i])); } return max; } public static void logInPlace(double[] vec) { for (int i = 0; i < vec.length; i++) { vec[i] = Math.log(vec[i]); } } public static void checkNonInfinite(double[] vec) { for (double v : vec) { if (Double.isInfinite(v)) { throw new RuntimeException("Invalid Entry: " + v); } } } public static void checkNonInfinite(double[][] m) { for (double[] row : m) { checkNonInfinite(row); } } public static void addInPlace(double[] a, double[] b, double c) { for (int i = 0; i < a.length; i++) { a[i] += b[i] * c; } } public static void addInPlace(double[][] a, double[][] b, double c) { for (int i = 0; i < a.length; i++) { addInPlace(a[i],b[i],c); } } public static double[] multiply(double[][] X, double[] y) { int m = X.length; int n = X[0].length; assert n == y.length; double[] result = new double[m]; for (int i = 0; i < result.length; i++) { result[i] = DoubleArrays.innerProduct(X[i],y); } return result; } public static double[][] clone(double[][] M) { double[][] copy = new double[M.length][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static double[][][] clone(double[][][] M ) { double[][][] copy = new double[M.length][][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static double[][][][] clone(double[][][][] M ) { double[][][][] copy = new double[M.length][][][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static float[] clone(float[] x) { float[] y = new float[x.length]; assign(y, x); return y; } public static void assign(float[] y, float[] x) { if (x.length != y.length) throw new RuntimeException("diff lengths: " + x.length + " " + y.length); System.arraycopy(x, 0, y, 0, x.length); } public static float[][] clone(float[][] M) { float[][] copy = new float[M.length][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static float[][][] clone(float[][][] M ) { float[][][] copy = new float[M.length][][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static float[][][][] clone(float[][][][] M ) { float[][][][] copy = new float[M.length][][][]; for (int i = 0; i < M.length; i++) { copy[i] = clone(M[i]); } return copy; } public static double outerProduct(double[][] M, double[] x) { double sum = 0.0; for (int i = 0; i < M.length; i++) { for (int j = 0; j < M[i].length; j++) { sum += M[i][j] * x[i] * x[j]; } } return sum; } }