package arkref.ext.fig.basic; import java.util.*; import java.lang.reflect.*; public class ListUtils { public static ArrayList<Double> toList(double[] xs) { ArrayList<Double> list = new ArrayList(); for(double x : xs) list.add(x); return list; } public static<T> ArrayList<T> toList(Iterable<T> it) { if(it instanceof ArrayList) return (ArrayList)it; ArrayList<T> list = new ArrayList<T>(); for(T x : it) list.add(x); return list; } public static<T> ArrayList<T> newList(T... list) { return new ArrayList<T>(Arrays.asList(list)); } public static<T> ArrayList<T> newListFill(T x, int n) { ArrayList<T> list = new ArrayList<T>(n); for(int i = 0; i < n; i++) list.add(x); return list; } public static int maxStringLength(List<String> strings) { int l = 0; for(String s : strings) l = Math.max(l, s.length()); return l; } public static <T> Map<T, Integer> buildHistogram(Collection<T> c) { Map<T, Integer> counts = new HashMap<T, Integer>(); for(T x : c) MapUtils.incr(counts, x); return counts; } public static <T> void randomPermute(List<T> l, Random rand) { for(int i = 0; i < l.size(); i++) { int j = i+rand.nextInt(l.size()-i); T x = l.get(i); l.set(i, l.get(j)); l.set(j, x); } } public static <T> T getLast(List<T> l) { return get(l, -1); } public static <T> T get(List<T> l, int i) { return get(l, i, null); } public static <T> T get(List<T> l, int i, T defValue) { if(i < 0) i += l.size(); if(i < 0 || i >= l.size()) return defValue; return l.get(i); } public static <T> T removeLast(List<T> l) { return l.remove(l.size()-1); } public static <T> T getLast(T[] l) { return get(l, -1); } public static <T> T get(T[] l, int i) { return get(l, i, null); } public static <T> T get(T[] l, int i, T defValue) { if(i < 0) i += l.length; if(i < 0 || i >= l.length) return defValue; return l[i]; } public static double get(double[] l, int i, double defValue) { if(i < 0) i += l.length; if(i < 0 || i >= l.length) return defValue; return l[i]; } public static <T> int indexOf(T[] v, T x) { if(x == null) { for(int i = 0; i < v.length; i++) if(v[i] == null) return i; } else { for(int i = 0; i < v.length; i++) if(x.equals(v[i])) return i; } return -1; } public static int indexOf(int[] v, int x) { for(int i = 0; i < v.length; i++) if(x == v[i]) return i; return -1; } public static <T> int countOf(T[] v, T x) { int n = 0; if(x == null) { for(int i = 0; i < v.length; i++) if(v[i] == null) n++; } else { for(int i = 0; i < v.length; i++) if(x.equals(v[i])) n++; } return n; } public static int countOf(boolean[] v, boolean x) { int n = 0; for(int i = 0; i < v.length; i++) if(x == v[i]) n++; return n; } // Return the array (0, 1, 2, ..., n-1) public static int[] identityMapArray(int n) { int[] arr = new int[n]; for(int i = 0; i < n; i++) arr[i] = i; return arr; } public static int minIndex(double[] list) { int bi = -1; for(int i = 0; i < list.length; i++) if(bi == -1 || list[i] < list[bi]) bi = i; return bi; } public static int maxIndex(int[] list) { int bi = -1; for(int i = 0; i < list.length; i++) if(bi == -1 || list[i] > list[bi]) bi = i; return bi; } public static int maxIndex(double[] list) { int bi = -1; for(int i = 0; i < list.length; i++) if(bi == -1 || list[i] > list[bi]) bi = i; return bi; } public static double max(double[] list) { double m = Double.NEGATIVE_INFINITY; for(double x : list) m = Math.max(m, x); return m; } public static double max(double[][] mat) { double m = Double.NEGATIVE_INFINITY; for(double[] list : mat) for(double x : list) m = Math.max(m, x); return m; } public static int max(int[] list) { int m = Integer.MIN_VALUE; for(int x : list) m = Math.max(m, x); return m; } public static int sum(int[] list) { int sum = 0; for(int x : list) sum += x; return sum; } public static double mean(double[] list) { return sum(list)/list.length; } public static double sum(double[] list) { double sum = 0; for(double x : list) sum += x; return sum; } public static double sum(double[][] list) { double sum = 0; for(double[] x : list) sum += sum(x); return sum; } public static double sum(List<Double> list) { double sum = 0; for(double x : list) sum += x; return sum; } public static double logSum(double[] list) { double sum = Double.NEGATIVE_INFINITY; for(double x : list) sum = NumUtils.logAdd(sum, x); return sum; } public static double[] expMut(double[] list) { for(int i = 0; i < list.length; i++) list[i] = Math.exp(list[i]); return list; } public static double[] exp(double[] list) { double[] newlist = new double[list.length]; for(int i = 0; i < list.length; i++) newlist[i] = Math.exp(list[i]); return newlist; } public static double[] log(double[] list) { double[] newlist = new double[list.length]; for(int i = 0; i < list.length; i++) newlist[i] = Math.log(list[i]); return newlist; } // Return a permuted array. // Example: // data = (A, B, C), perm = (2, 0, 1) // newData = (C, A, B) public static int[] applyPermutation(int[] data, int[] perm) { assert data.length == perm.length; int[] newData = new int[data.length]; for(int i = 0; i < data.length; i++) newData[i] = data[perm[i]]; return newData; } public static double[] applyPermutation(double[] data, int[] perm) { assert data.length == perm.length; double[] newData = new double[data.length]; for(int i = 0; i < data.length; i++) newData[i] = data[perm[i]]; return newData; } public static <T> T[] applyPermutation(T[] data, int[] perm) { assert data.length == perm.length; T[] newData = newArray(data); for(int i = 0; i < data.length; i++) newData[i] = data[perm[i]]; return newData; } public static double[] applyInversePermutation(double[] data, int[] perm) { assert data.length == perm.length; double[] newData = new double[data.length]; for(int i = 0; i < data.length; i++) newData[perm[i]] = data[i]; return newData; } public static int[] inversePermutation(int[] perm) { // perm could be partial (with -1 entries) int[] newperm = newInt(perm.length, -1); for(int i = 0; i < perm.length; i++) if(perm[i] != -1) newperm[perm[i]] = i; return newperm; } public static void assertIsPermutation(int[] perm) { boolean hit[] = new boolean[perm.length]; for(int i : perm) { assert !hit[i]; hit[i] = true; } } public static int[] append(int[] a, int[] b) { int[] c = new int[a.length+b.length]; int j = 0; for(int i = 0; i < a.length; i++, j++) c[j] = a[i]; for(int i = 0; i < b.length; i++, j++) c[j] = b[i]; return c; } public static double[] append(double[] a, double[] b) { double[] c = new double[a.length+b.length]; int j = 0; for(int i = 0; i < a.length; i++, j++) c[j] = a[i]; for(int i = 0; i < b.length; i++, j++) c[j] = b[i]; return c; } public static <T> T[] append(T[] a, T[] b) { T[] c = newArray(a.length+b.length, a[0]); int j = 0; for(int i = 0; i < a.length; i++, j++) c[j] = a[i]; for(int i = 0; i < b.length; i++, j++) c[j] = b[i]; return c; } public static Integer[] toObjArray(int[] v) { Integer[] newv = new Integer[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i]; return newv; } public static Double[] toObjArray(double[] v) { Double[] newv = new Double[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i]; return newv; } public static Double[][] toObjArray(double[][] v) { Double[][] newv = new Double[v.length][]; for(int i = 0; i < v.length; i++) { newv[i] = new Double[v[i].length]; for(int j = 0; j < v[i].length; j++) newv[i][j] = v[i][j]; } return newv; } public static Integer[][] toObjArray(int[][] v) { Integer[][] newv = new Integer[v.length][]; for(int i = 0; i < v.length; i++) { newv[i] = new Integer[v[i].length]; for(int j = 0; j < v[i].length; j++) newv[i][j] = v[i][j]; } return newv; } public static <T> Object[] toObjectArray(T[] v) { Object[] newv = new Object[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i]; return newv; } public static boolean[] shallowClone(boolean[] v) { if(v == null) return null; return (boolean[])v.clone(); } public static int[] shallowClone(int[] v) { if(v == null) return null; return (int[])v.clone(); } public static double[][] shallowClone(double[][] v) { if(v == null) return null; double[][] newv = new double[v.length][]; for(int i = 0; i < v.length; i++) newv[i] = shallowClone(v[i]); return newv; } public static double[] shallowClone(double[] v) { if(v == null) return null; return (double[])v.clone(); } public static <T> T[][] shallowClone(T[][] v) { if(v == null) return null; T[][] newv = newArray(v); for(int i = 0; i < v.length; i++) { newv[i] = newArray(v[i]); for(int j = 0; j < v[i].length; j++) newv[i][j] = v[i][j]; // Don't make a copy } return newv; } public static <T> T[] shallowClone(T[] v) { if(v == null) return null; T[] newv = newArray(v); for(int i = 0; i < v.length; i++) newv[i] = v[i]; // Don't make a copy return newv; } public static <T> T[] deepClone(T[] v) { if(v == null) return null; T[] newv = newArray(v); for(int i = 0; i < v.length; i++) newv[i] = ((DeepCloneable<T>)v[i]).deepClone(); return newv; } public static <T> List<T> deepClone(List<T> v) { if(v == null) return null; List<T> newv = new ArrayList(); for(T x : v) newv.add(((DeepCloneable<T>)x).deepClone()); return newv; } public static <T> T[] newArray(T[] v) { return (T[])Array.newInstance(v.getClass().getComponentType(), v.length); } public static int[][] newInt(int nr, int nc, int x) { int[][] v = new int[nr][nc]; for(int r = 0; r < nr; r++) for(int c = 0; c < nc; c++) v[r][c] = x; return v; } public static double[][] newDouble(int nr, int nc, double x) { double[][] v = new double[nr][nc]; for(int r = 0; r < nr; r++) for(int c = 0; c < nc; c++) v[r][c] = x; return v; } public static double[][] newDouble(int nr, int[] nc, double x) { double[][] v = new double[nr][]; for(int r = 0; r < nr; r++) { v[r] = new double[nc[r]]; for(int c = 0; c < nc[r]; c++) v[r][c] = x; } return v; } public static double[][][] newDouble(int nr, int nc, int nk, double x) { double[][][] v = new double[nr][nc][nk]; for(int r = 0; r < nr; r++) for(int c = 0; c < nc; c++) for(int k = 0; k < nk; k++) v[r][c][k] = x; return v; } public static double[] newDouble(int n, double x) { double[] v = new double[n]; Arrays.fill(v, x); return v; } public static int[] newInt(int n, int x) { int[] v = new int[n]; Arrays.fill(v, x); return v; } public static interface Generator<T> { public T generate(int i); } public static <T> T[] newArray(int n, Class c, Generator<T> gen) { T[] a = (T[])Array.newInstance(c, n); for(int i = 0; i < n; i++) a[i] = gen.generate(i); return a; } public static <T> T[] newArray(int n, T x) { T[] a = (T[])Array.newInstance(x.getClass(), n); for(int i = 0; i < n; i++) a[i] = x; return a; } public static double[] mult(double f, double[] vec) { double[] newVec = new double[vec.length]; for(int i = 0; i < vec.length; i++) newVec[i] = f * vec[i]; return newVec; } public static void multMut(double[] vec, double f) { for(int i = 0; i < vec.length; i++) vec[i] *= f; } public static void multMut(double[][] mat, double f) { for(double[] vec : mat) multMut(vec, f); } // v1 += factor * v2 public static double[] incr(double[] v1, double factor, double[] v2) { for(int i = 0; i < v1.length; i++) v1[i] += factor * v2[i]; return v1; } public static double[] incr(double[] v1, double x) { for(int i = 0; i < v1.length; i++) v1[i] += x; return v1; } public static int[] set(int[] v, int x) { for(int i = 0; i < v.length; i++) v[i] = x; return v; } public static int[] set(int[] v, int x[], int n) { for(int i = 0; i < n; i++) v[i] = x[i]; return v; } public static int[] set(int[] v, int x[]) { return set(v, x, v.length); } public static double[] set(double[] v, double x[]) { for(int i = 0; i < v.length; i++) v[i] = x[i]; return v; } public static double[] set(double[] v, double x) { for(int i = 0; i < v.length; i++) v[i] = x; return v; } public static double[][] set(double[][] v, double[][] x) { for(int i = 0; i < v.length; i++) for(int j = 0; j < v[i].length; j++) v[i][j] = x[i][j]; return v; } public static double[][] set(double[][] v, double x) { for(int i = 0; i < v.length; i++) set(v[i], x); return v; } public static double[][][] set(double[][][] v, double x) { for(int i = 0; i < v.length; i++) set(v[i], x); return v; } public static double[][][][] set(double[][][][] v, double x) { for(int i = 0; i < v.length; i++) set(v[i], x); return v; } public static double[][][][][] set(double[][][][][] v, double x) { for(int i = 0; i < v.length; i++) set(v[i], x); return v; } public static double[] add(double[] v1, double[] v2) { double[] sumv = new double[v1.length]; for(int i = 0; i < v1.length; i++) sumv[i] = v1[i] + v2[i]; return sumv; } public static double[] addMut(double[] v1, double[] v2) { for(int i = 0; i < v1.length; i++) v1[i] += v2[i]; return v1; } public static double[] add(double[] v1, int[] v2) { double[] sumv = new double[v1.length]; for(int i = 0; i < v1.length; i++) sumv[i] = v1[i] + v2[i]; return sumv; } public static double[] sub(double[] v1, double[] v2) { double[] sumv = new double[v1.length]; for(int i = 0; i < v1.length; i++) sumv[i] = v1[i] - v2[i]; return sumv; } public static double[] sub(double[] v1, double x) { return add(v1, -x); } public static double[] add(double[] v1, double x) { double[] sumv = new double[v1.length]; for(int i = 0; i < v1.length; i++) sumv[i] = v1[i] + x; return sumv; } public static double[] mult(double[] v1, double[] v2) { double[] v = new double[v1.length]; for(int i = 0; i < v1.length; i++) v[i] = v1[i] * v2[i]; return v; } public static double[] multMut(double[] v1, double[] v2) { for(int i = 0; i < v1.length; i++) v1[i] *= v2[i]; return v1; } public static double dot(double[] v1, double[] v2) { double sum = 0; for(int i = 0; i < v1.length; i++) sum += v1[i] * v2[i]; return sum; } public static double[] sq(double[] v) { double[] newv = new double[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i]*v[i]; return newv; } public static double[] sqrt(double[] v) { double[] newv = new double[v.length]; for(int i = 0; i < v.length; i++) newv[i] = Math.sqrt(v[i]); return newv; } public static double[] reverse(double[] v) { double[] newv = new double[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[v.length-i-1]; return newv; } public static int[] reverse(int[] v) { int[] newv = new int[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[v.length-i-1]; return newv; } /* public static int[] toArray(List<Integer> list) { int[] array = new int[list.size()]; for(int i = 0; i < array.length; i++) array[i] = list.get(i); return array; } public static double[] toArray(List<Double> list) { double[] array = new double[list.size()]; for(int i = 0; i < array.length; i++) array[i] = list.get(i); return array; } public static String[] toArray(List<String> list) { String[] data = new String[list.size()]; for(int i = 0; i < data.length; i++) data[i] = list.get(i); return data; } public static int[][] toArray(List<int[]> list) { int[][] data = new int[list.size()][]; for(int i = 0; i < data.length; i++) data[i] = list.get(i); return data; } */ public static double[] concat(double[] v1, double[] v2) { double[] v = new double[v1.length+v2.length]; for(int i = 0; i < v1.length; i++) v[i] = v1[i]; for(int i = 0; i < v2.length; i++) v[v1.length+i] = v2[i]; return v; } public static <T> T[] concat(T[] v1, T[] v2) { T[] v = newArray(v1.length+v2.length, v1.length > 0 ? v1[0] : v2[0]); for(int i = 0; i < v1.length; i++) v[i] = v1[i]; for(int i = 0; i < v2.length; i++) v[v1.length+i] = v2[i]; return v; } // Take subsequence [start, end) public static String[] subArray(String[] v, int start) { return subArray(v, start, v.length); } public static String[] subArray(String[] v, int start, int end) { String[] subv = new String[end-start]; for(int i = start; i < end; i++) subv[i-start] = v[i]; return subv; } public static double[] subArray(double[] v, int start) { return subArray(v, start, v.length); } public static double[] subArray(double[] v, int start, int end) { double[] subv = new double[end-start]; for(int i = start; i < end; i++) subv[i-start] = v[i]; return subv; } public static int[] subArray(int[] v, int start) { return subArray(v, start, v.length); } public static int[] subArray(int[] v, int start, int end) { int[] subv = new int[end-start]; for(int i = start; i < end; i++) subv[i-start] = v[i]; return subv; } public static <T> T[] subArray(T[] v, int start, int end) { T[] subv = newArray(end-start, v[0]); for(int i = start; i < end; i++) subv[i-start] = v[i]; return subv; } public static <T> T[] subArray(T[] v, List<Integer> indices) { T[] newv = newArray(indices.size(), v[0]); for(int i = 0; i < indices.size(); i++) newv[i] = v[indices.get(i)]; return newv; } public static <T> List<T> subArray(List<T> v, int[] indices) { List<T> newv = new ArrayList(); for(int i : indices) if(i != -1) newv.add(v.get(i)); return newv; } // If bounds are invalid, clip them. public static <T> List<T> subList(List<T> list, int start) { return subList(list, start, list.size()); } public static <T> List<T> subList(List<T> list, int start, int end) { if(end < 0) end += list.size(); if(start < 0) start += list.size(); start = NumUtils.bound(start, 0, list.size()); end = NumUtils.bound(end, 0, list.size()); return list.subList(start, end); } public static <T> void partialSort(List<T> list, int numTop, Comparator<? super T> c) { Object[] a = list.toArray(); partialSort(a, numTop, (Comparator)c); ListIterator<T> i = list.listIterator(); for(int j=0; j<a.length; j++) { i.next(); i.set((T)a[j]); } } public static <T> void partialSort(T[] list, int numTop, Comparator<? super T> c) { // Select out the numTop-th ranked element // TODO Arrays.sort(list, c); // For now, sort everything } // Return the indices: the first element contains the smallest public static int[] sortedIndices(double[] list, boolean reverse) { int n = list.length; // Sort List<Pair<Double,Integer>> pairList = new ArrayList<Pair<Double,Integer>>(n); for(int i = 0; i < n; i++) pairList.add(new Pair<Double,Integer>(list[i], i)); Collections.sort(pairList, reverse ? new Pair.ReverseFirstComparator<Double,Integer>() : new Pair.FirstComparator<Double,Integer>()); // Extract the indices int[] indices = new int[n]; for(int i = 0; i < n; i++) indices[i] = pairList.get(i).getSecond(); return indices; } public static int[] sortedIndices(int[] list, boolean reverse) { int n = list.length; // Sort List<Pair<Integer,Integer>> pairList = new ArrayList<Pair<Integer,Integer>>(n); for(int i = 0; i < n; i++) pairList.add(new Pair<Integer,Integer>(list[i], i)); Collections.sort(pairList, reverse ? new Pair.ReverseFirstComparator<Integer,Integer>() : new Pair.FirstComparator<Integer,Integer>()); // Extract the indices int[] indices = new int[n]; for(int i = 0; i < n; i++) indices[i] = pairList.get(i).getSecond(); return indices; } public static <T> int[] toInt(T[] v) { if(v == null) return null; int[] newv = new int[v.length]; for(int i = 0; i < v.length; i++) newv[i] = (int)((Integer)v[i]); return newv; } public static int[] toInt(boolean[] v) { int[] newv = new int[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i] ? 1 : 0; return newv; } public static double[] toDouble(int[] v) { double[] newv = new double[v.length]; for(int i = 0; i < v.length; i++) newv[i] = v[i]; return newv; } public static boolean equals(int[] a, int[] b) { if(a.length != b.length) return false; for(int i = 0; i < a.length; i++) if(a[i] != b[i]) return false; return true; } public static double[] getCol(double[][] mat, int c) { double[] v = new double[mat.length]; for(int r = 0; r < v.length; r++) v[r] = mat[r][c]; return v; } public static void setCol(double[][] mat, int c, double[] v) { for(int r = 0; r < v.length; r++) mat[r][c] = v[r]; } }