package cz.cuni.lf1.lge.ThunderSTORM.util; import cz.cuni.lf1.lge.ThunderSTORM.FormulaParser.FormulaParserException; import java.util.Arrays; public class VectorMath { public static Double[] relEq(Double[] vec, Double val) { return relEq(val, vec); } public static Double[] relEq(Double val, Double[] vec) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((v == vec[i].doubleValue()) ? 1.0 : 0.0); } return res; } public static Double[] relEq(Double[] a, Double[] b) { int len1; int len2; if(a.length < b.length) { len1 = a.length; len2 = b.length; } else { len1 = b.length; len2 = a.length; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = ((a[i].doubleValue() == b[i].doubleValue()) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = 0.0; } return res; } /** * Compute the sum of an array of doubles. * * @param arr an array of doubles * @return { * @mathjax \sum_{i=0}^{arr.length}{arr[i]}} */ public static double sum(double[] arr) { double sum = 0.0; for(int i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } /** * Compute the sum of an array of floats. * * @param arr an array of floats * @return { * @mathjax \sum_{i=0}^{arr.length}{arr[i]}} */ public static float sum(float[] arr) { float sum = 0.0F; for(int i = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } public static void cumulativeSum(double[] arr, boolean reverseDirection) { double sum = 0; if(!reverseDirection) { for(int i = 0; i < arr.length; i++) { sum += arr[i]; arr[i] = sum; } } else { for(int i = arr.length - 1; i >= 0; i--) { sum += arr[i]; arr[i] = sum; } } } public static Double sum(Number[] arr) { double sum = 0.0; for(int i = 0; i < arr.length; i++) { sum += arr[i].doubleValue(); } return new Double(sum); } public static Double[] relLt(Double[] vec, Double val) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((vec[i].doubleValue() < v) ? 1.0 : 0.0); } return res; } public static Double[] relLt(Double val, Double[] vec) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((v < vec[i].doubleValue()) ? 1.0 : 0.0); } return res; } public static Double[] relLt(Double[] a, Double[] b) { int len1; int len2; if(a.length < b.length) { len1 = a.length; len2 = b.length; } else { len1 = b.length; len2 = a.length; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = ((a[i].doubleValue() < b[i].doubleValue()) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = 0.0; } return res; } /** * Compute the median of an array of floats. * * @param arr an array of floats * @return The median is found by arranging all the observations from lowest * value to highest value and picking the middle one (eg, the median of {3, * 5, 9} is 5). If there is an even number of observations, then there is no * single middle value; the median is then defined to be the mean of the two * middle values. */ public static float median(float[] arr) { float[] sorted = Arrays.copyOf(arr, arr.length); Arrays.sort(sorted); if((sorted.length % 2) == 1) { return sorted[sorted.length / 2]; } else { return (sorted[sorted.length / 2] + sorted[1 + sorted.length / 2]) / 2.0F; } } public static Number median(Number[] arr) { Number[] sorted = Arrays.copyOf(arr, arr.length); Arrays.sort(sorted); if((sorted.length % 2) == 1) { return sorted[sorted.length / 2]; } else { return new Double((sorted[sorted.length / 2].doubleValue() + sorted[1 + sorted.length / 2].doubleValue()) / 2.0); } } public static int max(int[] array) { int max = array[0]; for(int i = 0; i < array.length; i++) { if(array[i] > max) { max = array[i]; } } return max; } public static double max(double[] array) { double max = array[0]; for(int i = 0; i < array.length; i++) { if(array[i] > max) { max = array[i]; } } return max; } public static Number max(Number[] array) { Number max = array[0]; for(int i = 0; i < array.length; i++) { if(array[i].doubleValue() > max.doubleValue()) { max = array[i]; } } return max; } public static Double[] relNeq(Double[] vec, Double val) { return relNeq(val, vec); } public static Double[] relNeq(Double val, Double[] vec) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((v != vec[i].doubleValue()) ? 1.0 : 0.0); } return res; } public static Double[] relNeq(Double[] a, Double[] b) { int len1; int len2; if(a.length < b.length) { len1 = a.length; len2 = b.length; } else { len1 = b.length; len2 = a.length; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = ((a[i].doubleValue() != b[i].doubleValue()) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = 0.0; } return res; } public static Double[] mod(Number val, Number[] arr) { Double[] res = new Double[arr.length]; double tmp; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { tmp = v / arr[i].doubleValue(); res[i] = v - (((double) ((int) tmp)) * arr[i].doubleValue()); } return res; } public static Double[] mod(Number[] arr, Number val) { Double[] res = new Double[arr.length]; double tmp; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { tmp = arr[i].doubleValue() / v; res[i] = arr[i].doubleValue() - (((double) ((int) tmp)) * v); } return res; } public static Double[] mod(Number[] arr1, Number[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When performing modulo operation of two vectors (item-by-item), both must be of the same size!"); } Double[] res = new Double[arr1.length]; double tmp; for(int i = 0; i < arr1.length; i++) { tmp = arr1[i].doubleValue() / arr2[i].doubleValue(); res[i] = arr1[i].doubleValue() - (((double) ((int) tmp)) * arr2[i].doubleValue()); } return res; } /** * Compute the variance of an array of doubles. * * @param arr an array of doubles * @return statistical variance */ public static double var(double[] arr) { double sumdev = 0.0; double mean = mean(arr); for(int i = 0; i < arr.length; i++) { sumdev += MathProxy.sqr(arr[i] - mean); } return sumdev / (double) arr.length; } public static double [] div(double [] arr, double val) { double[] res = new double[arr.length]; for(int i = 0; i < arr.length; i++) { res[i] = arr[i] / val; } return res; } public static Double[] div(Number val, Number[] arr) { Double[] res = new Double[arr.length]; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { res[i] = new Double(v / arr[i].doubleValue()); } return res; } public static Double[] div(Number[] arr, Number val) { return mul(new Double(1.0 / val.doubleValue()), arr); } public static Double[] div(Number[] arr1, Number[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When dividing two vectors (item-by-item), both must be of the same size!"); } Double[] res = new Double[arr1.length]; for(int i = 0; i < arr1.length; i++) { res[i] = new Double(arr1[i].doubleValue() / arr2[i].doubleValue()); } return res; } public static Double[] pow(Number[] arr, Number val) { Double[] res = new Double[arr.length]; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { res[i] = new Double(MathProxy.pow(arr[i].doubleValue(), v)); } return res; } public static float min(float[] array) { float min = array[0]; for(int i = 0; i < array.length; i++) { if(array[i] < min) { min = array[i]; } } return min; } public static double min(double[] array) { double min = array[0]; for(int i = 0; i < array.length; i++) { if(array[i] < min) { min = array[i]; } } return min; } public static Number min(Number[] array) { Number min = array[0]; for(int i = 0; i < array.length; i++) { if(array[i].doubleValue() < min.doubleValue()) { min = array[i]; } } return min; } public static Double[] logOr(Double[] a, Double[] b) { int len1; int len2; Double[] larger; if(a.length < b.length) { len1 = a.length; len2 = b.length; larger = b; } else { len1 = b.length; len2 = a.length; larger = a; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = (((a[i].doubleValue() != 0.0) || (b[i].doubleValue() != 0.0)) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = larger[i]; } return res; } public static double[] add(double[] arr, double scalar) { if(scalar != 0) { for(int i = 0; i < arr.length; i++) { arr[i] += scalar; } } return arr; } public static Double[] add(Number[] arr, Number val) { Double[] res = new Double[arr.length]; for(int i = 0; i < arr.length; i++) { res[i] = new Double(arr[i].doubleValue() + val.doubleValue()); } return res; } public static Double[] add(Number[] arr1, Number[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When adding two vectors, both must be of the same size!"); } Double[] res = new Double[arr1.length]; for(int i = 0; i < arr1.length; i++) { res[i] = new Double(arr1[i].doubleValue() + arr2[i].doubleValue()); } return res; } public static Double[] abs(Double[] vec) { Double[] res = new Double[vec.length]; for(int i = 0; i < vec.length; i++) { res[i] = MathProxy.abs(vec[i]); } return res; } /** * Compute the standard deviation of an array of doubles. * * @param arr an array of doubles * @return { * @mathjax \sqrt{\frac{1}{arr.length} \sum_{i=0}^{arr.length}{\left(arr[i] * - \mu\right)}}}, where { * @mathjax \mu} = {@code mean(arr)}. */ public static double stddev(double[] arr) { return MathProxy.sqrt(var(arr)); } public static Double stddev(Number[] arr) { double sumdev = 0.0; double mean = mean(arr); for(int i = 0; i < arr.length; i++) { sumdev += MathProxy.sqr(arr[i].doubleValue() - mean); } return new Double(MathProxy.sqrt(sumdev / (double) arr.length)); } public static Double[] mul(Number val, Number[] arr) { Double[] res = new Double[arr.length]; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { res[i] = new Double(v * arr[i].doubleValue()); } return res; } public static Double[] mul(Number[] arr, Number val) { return mul(val, arr); } public static Double[] mul(Number[] arr1, Number[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When multiplying two vectors, both must be of the same size!"); } Double[] res = new Double[arr1.length]; for(int i = 0; i < arr1.length; i++) { res[i] = new Double(arr1[i].doubleValue() * arr2[i].doubleValue()); } return res; } public static Double[] relGt(Double[] vec, Double val) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((vec[i].doubleValue() > v) ? 1.0 : 0.0); } return res; } public static Double[] relGt(Double val, Double[] vec) { Double[] res = new Double[vec.length]; double v = val.doubleValue(); for(int i = 0; i < vec.length; i++) { res[i] = ((v > vec[i].doubleValue()) ? 1.0 : 0.0); } return res; } public static Double[] relGt(Double[] a, Double[] b) { int len1; int len2; if(a.length < b.length) { len1 = a.length; len2 = b.length; } else { len1 = b.length; len2 = a.length; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = ((a[i].doubleValue() > b[i].doubleValue()) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = 0.0; } return res; } public static Double[] logAnd(Double[] a, Double[] b) { int len1; int len2; if(a.length < b.length) { len1 = a.length; len2 = b.length; } else { len1 = b.length; len2 = a.length; } Double[] res = new Double[len2]; for(int i = 0; i < len1; i++) { res[i] = (((a[i].doubleValue() != 0.0) && (b[i].doubleValue() != 0.0)) ? 1.0 : 0.0); } for(int i = len1; i < len2; i++) { res[i] = 0.0; } return res; } /** * Compute the mean value of an array of doubles. * * @param arr an array of doubles * @return { * @mathjax \frac{1}{arr.length} \sum_{i=0}^{arr.length}{arr[i]}} */ public static double mean(double[] arr) { return sum(arr) / (double) arr.length; } public static Double mean(Number[] arr) { return new Double(sum(arr).doubleValue() / (double) arr.length); } public static Double[] sub(Number val, Number[] arr) { Double[] res = new Double[arr.length]; double v = val.doubleValue(); for(int i = 0; i < arr.length; i++) { res[i] = new Double(v - arr[i].doubleValue()); } return res; } public static Double[] sub(Number[] arr, Number val) { return add(arr, new Double(-val.doubleValue())); } public static Double[] sub(Number[] arr1, Number[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When subtracting two vectors, both must be of the same size!"); } Double[] res = new Double[arr1.length]; for(int i = 0; i < arr1.length; i++) { res[i] = new Double(arr1[i].doubleValue() - arr2[i].doubleValue()); } return res; } public static double[] sub(double[] arr1, double[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When subtracting two vectors, both must be of the same size!"); } double[] res = new double[arr1.length]; for(int i = 0; i < arr1.length; i++) { res[i] = arr1[i] - arr2[i]; } return res; } public static double[] sub(double[] res, double[] arr1, double[] arr2) { if(arr1.length != arr2.length) { throw new FormulaParserException("When subtracting two vectors, both must be of the same size!"); } if((res == null) || (res.length < arr1.length)) { res = new double[arr1.length]; } for(int i = 0; i < arr1.length; i++) { res[i] = arr1[i] - arr2[i]; } return res; } public static double[] movingAverage(double[] values, int lag) { if (lag <= 0 || lag % 2 == 0) { throw new IllegalArgumentException("`lag` must be a positive odd number!"); } double[] mavg = new double[values.length]; // moving sum mavg[0] = 0.0; for (int i = 0, l = lag / 2; i <= l && i < values.length; i++) { mavg[0] += values[i]; } for (int i = 1, l = lag / 2, sub = i - l - 1, add = i + l; i < mavg.length; i++, sub++, add++) { mavg[i] = mavg[i-1]; if (sub >= 0) mavg[i] -= values[sub]; if (add < values.length) mavg[i] += values[add]; } // moving average for (int i = 0, j = mavg.length - 1, l = lag / 2; i < mavg.length; i++, j--) { double count = (double) Math.min(lag - Math.max(Math.max(0, l - i), Math.max(0, l - j)), mavg.length); mavg[i] /= count; } return mavg; } }