package water.util;
import water.*;
import water.fvec.*;
import java.text.DecimalFormat;
import java.util.*;
import static java.lang.StrictMath.sqrt;
import static water.util.RandomUtils.getRNG;
/* Bulk Array Utilities */
public class ArrayUtils {
private static final byte[] EMPTY_BYTE_ARRAY = new byte[] {};
// Sum elements of an array
public static long sum(final long[] from) {
long result = 0;
for (long d: from) result += d;
return result;
}
public static long sum(final long[] from, int startIdx, int endIdx) {
long result = 0;
for (int i = startIdx; i < endIdx; i++) result += from[i];
return result;
}
public static int sum(final int[] from) {
int result = 0;
for( int d : from ) result += d;
return result;
}
public static float sum(final float[] from) {
float result = 0;
for (float d: from) result += d;
return result;
}
public static double sum(final double[] from) {
double result = 0;
for (double d: from) result += d;
return result;
}
public static float[] reduceMin(float[] a, float[] b) {
for (int i=0; i<a.length; ++i)
a[i] = Math.min(a[i], b[i]);
return a;
}
public static float[] reduceMax(float[] a, float[] b) {
for (int i=0; i<a.length; ++i)
a[i] = Math.max(a[i], b[i]);
return a;
}
public static double innerProduct(double [] x, double [] y){
double result = 0;
for (int i = 0; i < x.length; i++)
result += x[i] * y[i];
return result;
}
public static double [] mmul(double [][] M, double [] V) {
double [] res = new double[M.length];
for(int i = 0; i < M.length; ++i) {
double d = 0;
for (int j = 0; j < V.length; ++j) {
d += M[i][j] * V[j];
}
res[i] = d;
}
return res;
}
public static double[][] outerProduct(double[] x, double[] y){
double[][] result = new double[x.length][y.length];
for(int i = 0; i < x.length; i++) {
for(int j = 0; j < y.length; j++)
result[i][j] = x[i] * y[j];
}
return result;
}
// return the sqrt of each element of the array. Will overwrite the original array in this case
public static double[] sqrtArr(double [] x){
assert (x != null);
int len = x.length;
for (int index = 0; index < len; index++) {
assert (x[index]>=0.0);
x[index] = sqrt(x[index]);
}
return x;
}
public static double l2norm2(double [] x){ return l2norm2(x, false); }
public static double l2norm2(double [][] xs, boolean skipLast){
double res = 0;
for(double [] x:xs)
res += l2norm2(x,skipLast);
return res;
}
public static double l2norm2(double [] x, boolean skipLast){
double sum = 0;
int last = x.length - (skipLast?1:0);
for(int i = 0; i < last; ++i)
sum += x[i]*x[i];
return sum;
}
public static double l2norm2(double[] x, double[] y) { // Computes \sum_{i=1}^n (x_i - y_i)^2
assert x.length == y.length;
double sse = 0;
for(int i = 0; i < x.length; i++) {
double diff = x[i] - y[i];
sse += diff * diff;
}
return sse;
}
public static double l2norm2(double[][] x, double[][] y) {
assert x.length == y.length && x[0].length == y[0].length;
double sse = 0;
for(int i = 0; i < x.length; i++)
sse += l2norm2(x[i], y[i]);
return sse;
}
public static double l1norm(double [] x){ return l1norm(x, false); }
public static double l1norm(double [] x, boolean skipLast){
double sum = 0;
int last = x.length -(skipLast?1:0);
for(int i = 0; i < last; ++i)
sum += x[i] >= 0?x[i]:-x[i];
return sum;
}
public static double linfnorm(double [] x, boolean skipLast){
double res = Double.NEGATIVE_INFINITY;
int last = x.length -(skipLast?1:0);
for(int i = 0; i < last; ++i) {
if(x[i] > res) res = x[i];
if(-x[i] > res) res = -x[i];
}
return res;
}
public static double l2norm(double[] x) { return Math.sqrt(l2norm2(x)); }
public static double l2norm(double [] x, boolean skipLast){
return Math.sqrt(l2norm2(x, skipLast));
}
public static double l2norm(double[] x, double[] y) { return Math.sqrt(l2norm2(x,y)); }
public static double l2norm(double[][] x, double[][] y) { return Math.sqrt(l2norm2(x,y)); }
// Add arrays, element-by-element
public static byte[] add(byte[] a, byte[] b) {
for(int i = 0; i < a.length; i++ ) a[i] += b[i];
return a;
}
public static int[] add(int[] a, int[] b) {
for(int i = 0; i < a.length; i++ ) a[i] += b[i];
return a;
}
public static int[][] add(int[][] a, int[][] b) {
for(int i = 0; i < a.length; i++ ) add(a[i],b[i]);
return a;
}
public static long[] add(long[] a, long[] b) {
if( b==null ) return a;
for(int i = 0; i < a.length; i++ ) a[i] += b[i];
return a;
}
public static long[][] add(long[][] a, long[][] b) {
for(int i = 0; i < a.length; i++ ) add(a[i],b[i]);
return a;
}
public static long[][][] add(long[][][] a, long[][][] b) {
for(int i = 0; i < a.length; i++ ) add(a[i],b[i]);
return a;
}
public static float[] add(float[] a, float[] b) {
if( b==null ) return a;
for(int i = 0; i < a.length; i++ ) a[i] += b[i];
return a;
}
public static float[] add(float ca, float[] a, float cb, float[] b) {
for(int i = 0; i < a.length; i++ ) a[i] = (ca * a[i]) + (cb * b[i]);
return a;
}
public static float[][] add(float[][] a, float[][] b) {
for(int i = 0; i < a.length; i++ ) add(a[i],b[i]);
return a;
}
public static boolean[] or(boolean[] a, boolean[] b) {
if (b==null)return a;
for (int i = 0; i < a.length; i++) a[i] |= b[i];
return a;
}
public static double[][] deepClone(double [][] ary){
double [][] res = ary.clone();
for(int i = 0 ; i < res.length; ++i)
res[i] = ary[i].clone();
return res;
}
public static <T extends Iced> T[][] deepClone(T [][] ary){
T [][] res = ary.clone();
for(int i = 0 ; i < res.length; ++i)
res[i] = deepClone(res[i]);
return res;
}
public static <T extends Iced> T[] deepClone(T [] ary){
T [] res = ary.clone();
for(int j = 0; j < res.length; ++j)
if(res[j] != null)
res[j] = (T)res[j].clone();
return res;
}
public static double[] add(double[] a, double[] b) {
if( a==null ) return b;
for(int i = 0; i < a.length; i++ ) a[i] += b[i];
return a;
}
public static double[] add(double[] a, double b) {
for(int i = 0; i < a.length; i++ ) a[i] += b;
return a;
}
public static double[] wadd(double[] a, double[] b, double w) {
if( a==null ) return b;
for(int i = 0; i < a.length; i++ )
a[i] += w*b[i];
return a;
}
public static double[] wadd(double[] a, double[] b, double [] c, double w) {
if( a==null ) return b;
for(int i = 0; i < a.length; i++ )
c[i] = a[i] + w*b[i];
return c;
}
// a <- b + c
public static double[] add(double[] a, double[] b, double [] c) {
for(int i = 0; i < a.length; i++ )
a[i] = b[i] + c[i];
return a;
}
public static double[][] add(double[][] a, double[][] b) {
if (a == null) return b;
for(int i = 0; i < a.length; i++ ) a[i] = add(a[i], b[i]);
return a;
}
public static double[][][] add(double[][][] a, double[][][] b) {
for(int i = 0; i < a.length; i++ ) a[i] = add(a[i],b[i]);
return a;
}
public static double avg(double[] nums) {
double sum = 0;
for(double n: nums) sum+=n;
return sum/nums.length;
}
public static double avg(long[] nums) {
long sum = 0;
for(long n: nums) sum+=n;
return sum/nums.length;
}
public static long[] add(long[] nums, long a) {
for (int i=0;i<nums.length;i++) nums[i] += a;
return nums;
}
public static float[] div(float[] nums, int n) {
for (int i=0; i<nums.length; i++) nums[i] /= n;
return nums;
}
public static float[] div(float[] nums, float n) {
assert !Float.isInfinite(n) : "Trying to divide " + Arrays.toString(nums) + " by " + n; // Almost surely not what you want
for (int i=0; i<nums.length; i++) nums[i] /= n;
return nums;
}
public static double[] div(double[] nums, double n) {
assert !Double.isInfinite(n) : "Trying to divide " + Arrays.toString(nums) + " by " + n; // Almost surely not what you want
for (int i=0; i<nums.length; i++) nums[i] /= n;
return nums;
}
public static double[][] div(double[][] ds, long[] n) {
for (int i=0; i<ds.length; i++) div(ds[i],n[i]);
return ds;
}
public static double[][] div(double[][] ds, double[] n) {
for (int i=0; i<ds.length; i++) div(ds[i],n[i]);
return ds;
}
public static double[] div(double[] ds, long[] n) {
for (int i=0; i<ds.length; i++) ds[i]/=n[i];
return ds;
}
public static double[] div(double[] ds, double[] n) {
for (int i=0; i<ds.length; i++) ds[i]/=n[i];
return ds;
}
public static double[][] mult(double[][] ds, double[] n) {
for (int i=0; i<ds.length; i++) mult(ds[i],n[i]);
return ds;
}
public static float[] mult(float[] nums, float n) {
// assert !Float.isInfinite(n) : "Trying to multiply " + Arrays.toString(nums) + " by " + n; // Almost surely not what you want
for (int i=0; i<nums.length; i++) nums[i] *= n;
return nums;
}
public static double[] mult(double[] nums, double n) {
// assert !Double.isInfinite(n) : "Trying to multiply " + Arrays.toString(nums) + " by " + n; // Almost surely not what you want
for (int i=0; i<nums.length; i++) nums[i] *= n;
return nums;
}
public static double[][] mult(double[][] ary, double n) {
if(ary == null) return null;
for (double[] row : ary) mult(row, n);
return ary;
}
public static double[] mult(double[] nums, double[] nums2) {
for (int i=0; i<nums.length; i++) nums[i] *= nums2[i];
return nums;
}
public static double[] invert(double[] ary) {
if(ary == null) return null;
for(int i=0;i<ary.length;i++) ary[i] = 1. / ary[i];
return ary;
}
public static double[] multArrVec(double[][] ary, double[] nums) {
if(ary == null) return null;
double[] res = new double[ary.length];
return multArrVec(ary, nums, res);
}
public static double[] multArrVec(double[][] ary, double[] nums, double[] res) {
if(ary == null || nums == null) return null;
assert ary[0].length == nums.length : "Inner dimensions must match: Got " + ary[0].length + " != " + nums.length;
for(int i = 0; i < ary.length; i++)
res[i] = innerProduct(ary[i], nums);
return res;
}
public static double[] multVecArr(double[] nums, double[][] ary) {
if(ary == null || nums == null) return null;
assert nums.length == ary.length : "Inner dimensions must match: Got " + nums.length + " != " + ary.length;
double[] res = new double[ary[0].length];
for(int j = 0; j < ary[0].length; j++) {
res[j] = 0;
for(int i = 0; i < ary.length; i++)
res[j] += nums[i] * ary[i][j];
}
return res;
}
/*
with no memory allocation for results. We assume the memory is already allocated.
*/
public static double[][] multArrArr(double[][] ary1, double[][] ary2, double[][] res) {
if(ary1 == null || ary2 == null) return null;
// Inner dimensions must match
assert ary1[0].length == ary2.length : "Inner dimensions must match: Got " + ary1[0].length + " != " + ary2.length;
for(int i = 0; i < ary1.length; i++) {
for(int j = 0; j < ary2[0].length; j++) {
double tmp = 0;
for(int k = 0; k < ary1[0].length; k++)
tmp += ary1[i][k] * ary2[k][j];
res[i][j] = tmp;
}
}
return res;
}
/*
with memory allocation for results
*/
public static double[][] multArrArr(double[][] ary1, double[][] ary2) {
if(ary1 == null || ary2 == null) return null;
double[][] res = new double[ary1.length][ary2[0].length];
return multArrArr(ary1, ary2, res);
}
public static double[][] transpose(double[][] ary) {
if(ary == null) return null;
double[][] res = new double[ary[0].length][ary.length];
for(int i = 0; i < res.length; i++) {
for(int j = 0; j < res[0].length; j++)
res[i][j] = ary[j][i];
}
return res;
}
public static <T> T[] cloneOrNull(T[] ary){return ary == null?null:ary.clone();}
public static <T> T[][] transpose(T[][] ary) {
if(ary == null|| ary.length == 0) return ary;
T [][] res = Arrays.copyOf(ary,ary[0].length);
for(int i = 0; i < res.length; ++i)
res[i] = Arrays.copyOf(ary[0],ary.length);
for(int i = 0; i < res.length; i++) {
for(int j = 0; j < res[0].length; j++)
res[i][j] = ary[j][i];
}
return res;
}
/**
* Provide array from start to end in steps of 1
* @param start beginning value (inclusive)
* @param end ending value (exclusive)
* @return specified range of integers
*/
public static int[] range(int start, int end) {
int[] r = new int[end-start+1];
for(int i=0;i<r.length;i++)
r[i] = i+start;
return r;
}
/**
* Given a n by k matrix X, form its Gram matrix
* @param x Matrix of real numbers
* @param transpose If true, compute n by n Gram of rows = XX'
* If false, compute k by k Gram of cols = X'X
* @return A symmetric positive semi-definite Gram matrix
*/
public static double[][] formGram(double[][] x, boolean transpose) {
if (x == null) return null;
int dim_in = transpose ? x[0].length : x.length;
int dim_out = transpose ? x.length : x[0].length;
double[][] xgram = new double[dim_out][dim_out];
// Compute all entries on and above diagonal
if(transpose) {
for (int i = 0; i < dim_in; i++) {
// Outer product = x[i] * x[i]', where x[i] is col i
for (int j = 0; j < dim_out; j++) {
for (int k = j; k < dim_out; k++)
xgram[j][k] += x[j][i] * x[k][i];
}
}
} else {
for (int i = 0; i < dim_in; i++) {
// Outer product = x[i]' * x[i], where x[i] is row i
for (int j = 0; j < dim_out; j++) {
for (int k = j; k < dim_out; k++)
xgram[j][k] += x[i][j] * x[i][k];
}
}
}
// Fill in entries below diagonal since Gram is symmetric
for (int i = 0; i < dim_in; i++) {
for (int j = 0; j < dim_out; j++) {
for (int k = 0; k < j; k++)
xgram[j][k] = xgram[k][j];
}
}
return xgram;
}
public static double[][] formGram(double[][] x) { return formGram(x, false); }
public static double[] permute(double[] vec, int[] idx) {
if(vec == null) return null;
assert vec.length == idx.length : "Length of vector must match permutation vector length: Got " + vec.length + " != " + idx.length;
double[] res = new double[vec.length];
for(int i = 0; i < vec.length; i++)
res[i] = vec[idx[i]];
return res;
}
public static double[][] permuteCols(double[][] ary, int[] idx) {
if(ary == null) return null;
assert ary[0].length == idx.length : "Number of columns must match permutation vector length: Got " + ary[0].length + " != " + idx.length;
double[][] res = new double[ary.length][ary[0].length];
for(int j = 0; j < ary[0].length; j++) {
for(int i = 0; i < ary.length; i++)
res[i][j] = ary[i][idx[j]];
}
return res;
}
public static double[][] permuteRows(double[][] ary, int[] idx) {
if(ary == null) return null;
assert ary.length == idx.length : "Number of rows must match permutation vector length: Got " + ary.length + " != " + idx.length;
double[][] res = new double[ary.length][ary[0].length];
for(int i = 0; i < ary.length; i++)
res[i] = permute(ary[i], idx);
return res;
}
public static double [][] generateLineSearchVecs(double [] srcVec, double [] gradient, int n, final double step) {
double [][] res = new double[n][];
double x = step;
for(int i = 0; i < res.length; ++i) {
res[i] = MemoryManager.malloc8d(srcVec.length);
for(int j = 0; j < res[i].length; ++j)
res[i][j] = srcVec[j] + gradient[j] * x;
x *= step;
}
return res;
}
public static String arrayToString(int[] ary) {
if (ary == null || ary.length==0 ) return "";
int m = ary.length - 1;
StringBuilder sb = new StringBuilder();
for (int i = 0; ; i++) {
sb.append(ary[i]);
if (i == m) return sb.toString();
sb.append(", ");
}
}
// Convert array of primitives to an array of Strings.
public static String[] toString(long[] dom) {
String[] result = new String[dom.length];
for (int i=0; i<dom.length; i++) result[i] = String.valueOf(dom[i]);
return result;
}
public static String[] toString(int[] dom) {
String[] result = new String[dom.length];
for (int i=0; i<dom.length; i++) result[i] = String.valueOf(dom[i]);
return result;
}
public static String[] toString(Object[] ary) {
String[] result = new String[ary.length];
for (int i=0; i<ary.length; i++) {
Object o = ary[i];
if (o != null && o.getClass().isArray()) {
Class klazz = ary[i].getClass();
result[i] = byte[].class.equals(klazz) ? Arrays.toString((byte[]) o) :
short[].class.equals(klazz) ? Arrays.toString((short[]) o) :
int[].class.equals(klazz) ? Arrays.toString((int[]) o) :
long[].class.equals(klazz) ? Arrays.toString((long[]) o) :
boolean[].class.equals(klazz) ? Arrays.toString((boolean[]) o) :
float[].class.equals(klazz) ? Arrays.toString((float[]) o) :
double[].class.equals(klazz) ? Arrays.toString((double[]) o) : Arrays.toString((Object[]) o);
} else {
result[i] = String.valueOf(o);
}
}
return result;
}
public static boolean contains(String[] names, String name) {
if (null == names) return false;
for (String n : names) if (n.equals(name)) return true;
return false;
}
static public boolean contains(int[] a, int d) {
for (int anA : a) if (anA == d) return true;
return false;
}
public static <T> T[] subarray(T[] a, int off, int len) {
return Arrays.copyOfRange(a,off,off+len);
}
/** Returns the index of the largest value in the array.
* In case of a tie, an the index is selected randomly.
*/
public static int maxIndex(int[] from, Random rand) {
assert rand != null;
int result = 0;
int maxCount = 0; // count of maximal element for a 1 item reservoir sample
for( int i = 1; i < from.length; ++i ) {
if( from[i] > from[result] ) {
result = i;
maxCount = 1;
} else if( from[i] == from[result] ) {
if( rand.nextInt(++maxCount) == 0 ) result = i;
}
}
return result;
}
public static int maxIndex(float[] from, Random rand) {
assert rand != null;
int result = 0;
int maxCount = 0; // count of maximal element for a 1 item reservoir sample
for( int i = 1; i < from.length; ++i ) {
if( from[i] > from[result] ) {
result = i;
maxCount = 1;
} else if( from[i] == from[result] ) {
if( rand.nextInt(++maxCount) == 0 ) result = i;
}
}
return result;
}
public static int maxIndex(double[] from, Random rand) {
assert rand != null;
int result = 0;
int maxCount = 0; // count of maximal element for a 1 item reservoir sample
for( int i = 1; i < from.length; ++i ) {
if( from[i] > from[result] ) {
result = i;
maxCount = 1;
} else if( from[i] == from[result] ) {
if( rand.nextInt(++maxCount) == 0 ) result = i;
}
}
return result;
}
public static int maxIndex(int[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]>from[result]) result = i;
return result;
}
public static int maxIndex(long[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]>from[result]) result = i;
return result;
}
public static int maxIndex(long[] from, int off) {
int result = off;
for (int i = off+1; i<from.length; ++i)
if (from[i]>from[result]) result = i;
return result;
}
public static int maxIndex(float[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]>from[result]) result = i;
return result;
}
public static int maxIndex(double[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]>from[result]) result = i;
return result;
}
public static int minIndex(int[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]<from[result]) result = i;
return result;
}
public static int minIndex(float[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]<from[result]) result = i;
return result;
}
public static int minIndex(double[] from) {
int result = 0;
for (int i = 1; i<from.length; ++i)
if (from[i]<from[result]) result = i;
return result;
}
public static double maxValue(double[] ary) {
return maxValue(ary,0,ary.length);
}
public static double maxValue(double[] ary, int from, int to) {
double result = ary[from];
for (int i = from+1; i<to; ++i)
if (ary[i]>result) result = ary[i];
return result;
}
public static float maxValue(float[] ary) {
return maxValue(ary,0,ary.length);
}
public static float maxValue(float[] ary, int from, int to) {
float result = ary[from];
for (int i = from+1; i<to; ++i)
if (ary[i]>result) result = ary[i];
return result;
}
public static float minValue(float[] from) {
float result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]<result) result = from[i];
return result;
}
public static double minValue(double[] ary, int from, int to) {
double result = ary[from];
for (int i = from+1; i<to; ++i)
if (ary[i]<result) result = ary[i];
return result;
}
public static double minValue(double[] from) {
double result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]<result) result = from[i];
return result;
}
public static long maxValue(long[] from) {
long result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]>result) result = from[i];
return result;
}
public static long maxValue(int[] from) {
int result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]>result) result = from[i];
return result;
}
public static long minValue(long[] from) {
long result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]<result) result = from[i];
return result;
}
public static long minValue(int[] from) {
int result = from[0];
for (int i = 1; i<from.length; ++i)
if (from[i]<result) result = from[i];
return result;
}
// Find an element with linear search & return it's index, or -1
public static <T> int find(T[] ts, T elem) {return find(ts,elem,0);}
// Find an element with linear search & return it's index, or -1
public static <T> int find(T[] ts, T elem, int off) {
for (int i = off; i < ts.length; i++)
if (elem == ts[i] || elem.equals(ts[i]))
return i;
return -1;
}
public static int find(long[] ls, long elem) {
for(int i=0; i<ls.length; ++i )
if( elem==ls[i] ) return i;
return -1;
}
public static int find(int[] ls, int elem) {
for(int i=0; i<ls.length; ++i )
if( elem==ls[i] ) return i;
return -1;
}
// behaves like Arrays.binarySearch, but is slower -> Just good for tiny arrays (length<20)
public static int linearSearch(double[] vals, double v) {
final int N=vals.length;
for (int i=0; i<N; ++i) {
if (vals[i]==v) return i;
if (vals[i]>v) return -i-1;
}
return -1;
}
private static final DecimalFormat default_dformat = new DecimalFormat("0.#####");
public static String pprint(double[][] arr){
return pprint(arr, default_dformat);
}
// pretty print Matrix(2D array of doubles)
public static String pprint(double[][] arr,DecimalFormat dformat) {
int colDim = 0;
for( double[] line : arr )
colDim = Math.max(colDim, line.length);
StringBuilder sb = new StringBuilder();
int max_width = 0;
int[] ilengths = new int[colDim];
Arrays.fill(ilengths, -1);
for( double[] line : arr ) {
for( int c = 0; c < line.length; ++c ) {
double d = line[c];
String dStr = dformat.format(d);
if( dStr.indexOf('.') == -1 ) dStr += ".0";
ilengths[c] = Math.max(ilengths[c], dStr.indexOf('.'));
int prefix = (d >= 0 ? 1 : 2);
max_width = Math.max(dStr.length() + prefix, max_width);
}
}
for( double[] line : arr ) {
for( int c = 0; c < line.length; ++c ) {
double d = line[c];
String dStr = dformat.format(d);
if( dStr.indexOf('.') == -1 ) dStr += ".0";
for( int x = dStr.indexOf('.'); x < ilengths[c] + 1; ++x )
sb.append(' ');
sb.append(dStr);
if( dStr.indexOf('.') == -1 ) sb.append('.');
for( int i = dStr.length() - Math.max(0, dStr.indexOf('.')); i <= 5; ++i )
sb.append('0');
}
sb.append("\n");
}
return sb.toString();
}
public static int[] unpackInts(long... longs) {
int len = 2*longs.length;
int result[] = new int[len];
int i = 0;
for (long l : longs) {
result[i++] = (int) (l & 0xffffffffL);
result[i++] = (int) (l>>32);
}
return result;
}
private static void swap(long[] a, int i, int change) {
long helper = a[i];
a[i] = a[change];
a[change] = helper;
}
private static void swap(int[] a, int i, int change) {
int helper = a[i];
a[i] = a[change];
a[change] = helper;
}
/**
* Extract a shuffled array of integers
* @param a input array
* @param n number of elements to extract
* @param result array to store the results into (will be of size n)
* @param seed random number seed
* @param startIndex offset into a
* @return result
*/
public static int[] shuffleArray(int[] a, int n, int result[], long seed, int startIndex) {
if (n<=0) return result;
Random random = getRNG(seed);
if (result == null || result.length != n)
result = new int[n];
result[0] = a[startIndex];
for (int i = 1; i < n; i++) {
int j = random.nextInt(i+1);
if (j!=i) result[i] = result[j];
result[j] = a[startIndex+i];
}
for (int i = 0; i < n; ++i)
assert(ArrayUtils.contains(result, a[startIndex+i]));
return result;
}
public static void shuffleArray(int[] a, Random rng) {
int n = a.length;
for (int i = 0; i < n; i++) {
int change = i + rng.nextInt(n - i);
swap(a, i, change);
}
}
// Generate a n by m array of random numbers drawn from the standard normal distribution
public static double[][] gaussianArray(int n, int m) { return gaussianArray(n, m, System.currentTimeMillis()); }
public static double[][] gaussianArray(int n, int m, long seed) {
if(n <= 0 || m <= 0) return null;
double[][] result = new double[n][m];
Random random = getRNG(seed);
for(int i = 0; i < n; i++) {
for(int j = 0; j < m; j++)
result[i][j] = random.nextGaussian();
}
return result;
}
public static double[] gaussianVector(int n) { return gaussianVector(n, System.currentTimeMillis()); }
public static double[] gaussianVector(int n, long seed) { return gaussianVector(n, getRNG(seed)); }
public static double[] gaussianVector(int n, Random random) {
if(n <= 0) return null;
double[] result = new double[n]; // ToDo: Get rid of this new action.
for(int i = 0; i < n; i++)
result[i] = random.nextGaussian();
return result;
}
/** Remove the array allocation in this one */
public static double[] gaussianVector(long seed, double[] vseed) {
if (vseed == null)
return null;
Random random = getRNG(seed);
int arraySize = vseed.length;
for (int i=0; i < arraySize; i++) {
vseed[i] = random.nextGaussian();
}
return vseed;
}
/** Returns number of strings which represents a number. */
public static int numInts(String... a) {
int cnt = 0;
for(String s : a) if (isInt(s)) cnt++;
return cnt;
}
public static boolean isInt(String s) {
if (s == null || s.isEmpty()) return false;
int i = s.charAt(0)=='-' ? 1 : 0;
for(; i<s.length();i++) if (!Character.isDigit(s.charAt(i))) return false;
return true;
}
public static int[] toInt(String[] a, int off, int len) {
int[] res = new int[len];
for(int i=0; i<len; i++) res[i] = Integer.valueOf(a[off + i]);
return res;
}
public static Integer[] toIntegers(int[] a, int off, int len) {
Integer [] res = new Integer[len];
for(int i = 0; i < len; ++i)
res[i] = a[off+i];
return res;
}
public static int[] toInt(Integer[] a, int off, int len) {
int [] res = new int[len];
for(int i = 0; i < len; ++i)
res[i] = a[off+i];
return res;
}
/** Clever union of String arrays.
*
* For union of numeric arrays (strings represent integers) it is expecting numeric ordering.
* For pure string domains it is expecting lexicographical ordering.
* For mixed domains it always expects lexicographical ordering since such a domain were produce
* by a parser which sort string with Array.sort().
*
* PRECONDITION - string domain was sorted by Array.sort(String[]), integer domain by Array.sort(int[]) and switched to Strings !!!
*
* @param a a set of strings
* @param b a set of strings
* @return union of arrays
* // TODO: add tests
*/
public static String[] domainUnion(String[] a, String[] b) {
if (a == null) return b;
if (b == null) return a;
int cIinA = numInts(a);
int cIinB = numInts(b);
// Trivial case - all strings or ints, sorted
if (cIinA==0 && cIinB==0 // only strings
|| cIinA==a.length && cIinB==b.length ) // only integers
return union(a, b, cIinA==0);
// Be little bit clever here: sort string representing numbers first and append
// a,b were sorted by Array.sort() but can contain some numbers.
// So sort numbers in numeric way, and then string in lexicographical order
int[] ai = toInt(a, 0, cIinA); Arrays.sort(ai); // extract int part but sort it in numeric order
int[] bi = toInt(b, 0, cIinB); Arrays.sort(bi);
String[] ri = toString(union(ai,bi)); // integer part
String[] si = union(a, b, cIinA, a.length - cIinA, cIinB, b.length - cIinB, true);
return join(ri, si);
}
/** Union of given String arrays.
*
* The method expects ordering of domains in given order (lexicographical, numeric)
*
* @param a first array
* @param b second array
* @param lexo - true if domains are sorted in lexicographical order or false for numeric domains
* @return union of values in given arrays.
*
* precondition lexo ? a,b are lexicographically sorted : a,b are sorted numerically
* precondition a!=null && b!=null
*/
public static String[] union(String[] a, String[] b, boolean lexo) {
if (a == null) return b;
if (b == null) return a;
return union(a, b, 0, a.length, 0, b.length, lexo);
}
public static String[] union(String[] a, String[] b, int aoff, int alen, int boff, int blen, boolean lexo) {
assert a!=null && b!=null : "Union expect non-null input!";
String[] r = new String[alen+blen];
int ia = aoff, ib = boff, i = 0;
while (ia < aoff+alen && ib < boff+blen) {
int c = lexo ? a[ia].compareTo(b[ib]) : Integer.valueOf(a[ia]).compareTo(Integer.valueOf(b[ib]));
if ( c < 0) r[i++] = a[ia++];
else if (c == 0) { r[i++] = a[ia++]; ib++; }
else r[i++] = b[ib++];
}
if (ia < aoff+alen) while (ia<aoff+alen) r[i++] = a[ia++];
if (ib < boff+blen) while (ib<boff+blen) r[i++] = b[ib++];
return Arrays.copyOf(r, i);
}
/** Returns a union of given sorted arrays. */
public static int[] union(int[] a, int[] b) {
assert a!=null && b!=null : "Union expect non-null input!";
int[] r = new int[a.length+b.length];
int ia = 0, ib = 0, i = 0;
while (ia < a.length && ib < b.length) {
int c = a[ia]-b[ib];
if ( c < 0) r[i++] = a[ia++];
else if (c == 0) { r[i++] = a[ia++]; ib++; }
else r[i++] = b[ib++];
}
if (ia < a.length) while (ia<a.length) r[i++] = a[ia++];
if (ib < b.length) while (ib<b.length) r[i++] = b[ib++];
return Arrays.copyOf(r, i);
}
public static long[] join(long[] a, long[] b) {
long[] res = Arrays.copyOf(a, a.length+b.length);
System.arraycopy(b, 0, res, a.length, b.length);
return res;
}
public static float [] join(float[] a, float[] b) {
float[] res = Arrays.copyOf(a, a.length+b.length);
System.arraycopy(b, 0, res, a.length, b.length);
return res;
}
public static <T> T[] join(T[] a, T[] b) {
T[] res = Arrays.copyOf(a, a.length+b.length);
System.arraycopy(b, 0, res, a.length, b.length);
return res;
}
public static boolean hasNaNsOrInfs(double [] ary){
for(double d:ary)
if(Double.isNaN(d) || Double.isInfinite(d))
return true;
return false;
}
public static boolean hasNaNs(double [] ary){
for(double d:ary)
if(Double.isNaN(d))
return true;
return false;
}
public static boolean hasNaNsOrInfs(float [] ary){
for(float d:ary)
if(Double.isNaN(d) || Double.isInfinite(d))
return true;
return false;
}
/** Generates sequence (start, stop) of integers: (start, start+1, ...., stop-1) */
static public int[] seq(int start, int stop) {
assert start<stop;
int len = stop-start;
int[] res = new int[len];
for(int i=start; i<stop;i++) res[i-start] = i;
return res;
}
// warning: Non-Symmetric! Returns all elements in a that are not in b (but NOT the other way around)
static public int[] difference(int a[], int b[]) {
if (a == null) return new int[]{};
if (b == null) return a.clone();
int[] r = new int[a.length];
int cnt = 0;
for (int x : a) {
if (!contains(b, x)) r[cnt++] = x;
}
return Arrays.copyOf(r, cnt);
}
// warning: Non-Symmetric! Returns all elements in a that are not in b (but NOT the other way around)
static public String[] difference(String a[], String b[]) {
if (a == null) return new String[]{};
if (b == null) return a.clone();
String[] r = new String[a.length];
int cnt = 0;
for (String s : a) {
if (!contains(b, s)) r[cnt++] = s;
}
return Arrays.copyOf(r, cnt);
}
static public double[][] append( double[][] a, double[][] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
assert a[0].length==b[0].length;
double[][] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
static public byte[] append( byte[] a, byte[] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
byte[] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
static public int[] append( int[] a, int[] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
int[] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
static public long[] append( long[] a, long[] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
long[] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
static public double[] append( double[] a, double[] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
double[] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
static public String[] append( String[] a, String[] b ) {
if( a==null ) return b;
if( b==null ) return a;
if( a.length==0 ) return b;
if( b.length==0 ) return a;
String[] c = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,c,a.length,b.length);
return c;
}
// Java7+ @SafeVarargs
public static <T> T[] append(T[] a, T... b) {
if( a==null ) return b;
T[] tmp = Arrays.copyOf(a,a.length+b.length);
System.arraycopy(b,0,tmp,a.length,b.length);
return tmp;
}
public static int[] append(int[] a, int b) {
if( a==null || a.length == 0) return new int[]{b};
int[] tmp = Arrays.copyOf(a,a.length+1);
tmp[a.length] = b;
return tmp;
}
static public String[] prepend(String[] ary, String s) {
if (ary==null) return new String[] { s };
String[] nary = new String[ary.length+1];
nary[0] = s;
System.arraycopy(ary,0,nary,1,ary.length);
return nary;
}
static public <T> T[] copyAndFillOf(T[] original, int newLength, T padding) {
if(newLength < 0) throw new NegativeArraySizeException("The array size is negative.");
T[] newArray = Arrays.copyOf(original, newLength);
if(original.length < newLength) {
System.arraycopy(original, 0, newArray, 0, original.length);
Arrays.fill(newArray, original.length, newArray.length, padding);
} else
System.arraycopy(original, 0, newArray, 0, newLength);
return newArray;
}
static public double[] copyAndFillOf(double[] original, int newLength, double padding) {
if(newLength < 0) throw new NegativeArraySizeException("The array size is negative.");
double[] newArray = new double[newLength];
if(original.length < newLength) {
System.arraycopy(original, 0, newArray, 0, original.length);
Arrays.fill(newArray, original.length, newArray.length, padding);
} else
System.arraycopy(original, 0, newArray, 0, newLength);
return newArray;
}
static public long[] copyAndFillOf(long[] original, int newLength, long padding) {
if(newLength < 0) throw new NegativeArraySizeException("The array size is negative.");
long[] newArray = new long[newLength];
if(original.length < newLength) {
System.arraycopy(original, 0, newArray, 0, original.length);
Arrays.fill(newArray, original.length, newArray.length, padding);
} else
System.arraycopy(original, 0, newArray, 0, newLength);
return newArray;
}
static public int[] copyAndFillOf(int[] original, int newLength, int padding) {
if(newLength < 0) throw new NegativeArraySizeException("The array size is negative.");
int[] newArray = new int[newLength];
if(original.length < newLength) {
System.arraycopy(original, 0, newArray, 0, original.length);
Arrays.fill(newArray, original.length, newArray.length, padding);
} else
System.arraycopy(original, 0, newArray, 0, newLength);
return newArray;
}
static public double[] copyFromIntArray(int[] a) {
double[] da = new double[a.length];
for(int i=0;i<a.length;++i) da[i] = a[i];
return da;
}
public static int [] sortedMerge(int[] a, int [] b) {
int [] c = MemoryManager.malloc4(a.length + b.length);
int i = 0, j = 0;
for(int k = 0; k < c.length; ++k){
if(i == a.length) c[k] = b[j++];
else if(j == b.length)c[k] = a[i++];
else if(b[j] < a[i]) c[k] = b[j++];
else c[k] = a[i++];
}
return c;
}
// sparse sortedMerge (ids and vals)
public static void sortedMerge(int[] aIds, double [] aVals, int[] bIds, double [] bVals, int [] resIds, double [] resVals) {
int i = 0, j = 0;
for(int k = 0; k < resIds.length; ++k){
if(i == aIds.length){
System.arraycopy(bIds,j,resIds,k,resIds.length-k);
System.arraycopy(bVals,j,resVals,k,resVals.length-k);
j = bIds.length;
break;
}
if(j == bIds.length) {
System.arraycopy(aIds,i,resIds,k,resIds.length-k);
System.arraycopy(aVals,i,resVals,k,resVals.length-k);
i = aIds.length;
break;
}
if(aIds[i] > bIds[j]) {
resIds[k] = bIds[j];
resVals[k] = bVals[j];
++j;
} else {
resIds[k] = aIds[i];
resVals[k] = aVals[i];
++i;
}
}
assert i == aIds.length && j == bIds.length;
}
public static String[] select(String[] ary, int[] idxs) {
String [] res = new String[idxs.length];
for(int i = 0; i < res.length; ++i)
res[i] = ary[idxs[i]];
return res;
}
public static double[] select(double[] ary, int[] idxs) {
double [] res = MemoryManager.malloc8d(idxs.length);
for(int i = 0; i < res.length; ++i)
res[i] = ary[idxs[i]];
return res;
}
public static int[] select(int[] ary, int[] idxs) {
int [] res = MemoryManager.malloc4(idxs.length);
for(int i = 0; i < res.length; ++i)
res[i] = ary[idxs[i]];
return res;
}
public static double [] expandAndScatter(double [] ary, int N, int [] ids) {
assert ary.length == ids.length:"ary.length = " + ary.length + " != " + ids.length + " = ids.length";
double [] res = MemoryManager.malloc8d(N);
for(int i = 0; i < ids.length; ++i) res[ids[i]] = ary[i];
return res;
}
/**
* Sort an integer array of indices based on values
* Updates indices in place, keeps values the same
* @param idxs indices
* @param values values
*/
public static void sort(final int[] idxs, final double[] values) {
sort(idxs, values, 500);
}
public static void sort(final int[] idxs, final double[] values, int cutoff) {
if (idxs.length < cutoff) {
//hand-rolled insertion sort
for (int i = 0; i < idxs.length; i++) {
for (int j = i; j > 0 && values[idxs[j - 1]] > values[idxs[j]]; j--) {
int tmp = idxs[j];
idxs[j] = idxs[j - 1];
idxs[j - 1] = tmp;
}
}
} else {
Integer[] d = new Integer[idxs.length];
for (int i = 0; i < idxs.length; ++i) d[i] = idxs[i];
// Arrays.parallelSort(d, new Comparator<Integer>() {
Arrays.sort(d, new Comparator<Integer>() {
@Override
public int compare(Integer x, Integer y) {
return values[x] < values[y] ? -1 : (values[x] > values[y] ? 1 : 0);
}
});
for (int i = 0; i < idxs.length; ++i) idxs[i] = d[i];
}
}
public static double [] subtract (double [] a, double [] b) {
double [] c = MemoryManager.malloc8d(a.length);
subtract(a,b,c);
return c;
}
public static double[] subtract (double [] a, double [] b, double [] c) {
for(int i = 0; i < a.length; ++i)
c[i] = a[i] - b[i];
return c;
}
/** Flatenize given array.
*
* Example: [[1,2], [3,null], [4]] -> [1,2,3,null,4]
* @param arr array of arrays
* @param <T> any type
* @return flattened array, if input was null return null, if input was empty return null
*/
public static <T> T[] flat(T[][] arr) {
if (arr == null) return null;
if (arr.length == 0) return null;
int tlen = 0;
for (T[] t : arr) tlen += t.length;
T[] result = Arrays.copyOf(arr[0], tlen);
int j = arr[0].length;
for (int i = 1; i < arr.length; i++) {
System.arraycopy(arr[i], 0, result, j, arr[i].length);
j += arr[i].length;
}
return result;
}
public static double [][] convertTo2DMatrix(double [] x, int N) {
assert x.length % N == 0;
int len = x.length/N;
double [][] res = new double[len][];
for(int i = 0; i < len; ++i) {
res[i] = MemoryManager.malloc8d(N);
System.arraycopy(x,i*N,res[i],0,N);
}
return res;
}
public static double[] flat(double[][] arr) {
if (arr == null) return null;
if (arr.length == 0) return null;
int tlen = 0;
for (double[] t : arr) tlen += t.length;
double[] result = Arrays.copyOf(arr[0], tlen);
int j = arr[0].length;
for (int i = 1; i < arr.length; i++) {
System.arraycopy(arr[i], 0, result, j, arr[i].length);
j += arr[i].length;
}
return result;
}
public static Object[][] zip(Object[] a, Object[] b) {
if (a.length != b.length) throw new IllegalArgumentException("Cannot zip arrays of different lengths!");
Object[][] result = new Object[a.length][2];
for (int i = 0; i < a.length; i++) {
result[i][0] = a[i];
result[i][1] = b[i];
}
return result;
}
public static <K, V> int crossProductSize(Map<K, V[]> hyperSpace) {
int size = 1;
for (Map.Entry<K,V[]> entry : hyperSpace.entrySet()) {
V[] value = entry.getValue();
size *= value != null ? value.length : 1;
}
return size;
}
public static Integer[] interval(Integer start, Integer end) {
return interval(start, end, 1);
}
public static Integer[] interval(Integer start, Integer end, Integer step) {
int len = 1 + (end - start) / step; // Include both ends of interval
Integer[] result = new Integer[len];
for(int i = 0, value = start; i < len; i++, value += step) {
result[i] = value;
}
return result;
}
public static Float[] interval(Float start, Float end, Float step) {
int len = 1 + (int)((end - start) / step); // Include both ends of interval
Float[] result = new Float[len];
Float value = start;
for(int i = 0; i < len; i++, value = start + i*step) {
result[i] = value;
}
return result;
}
public static Double[] interval(Double start, Double end, Double step) {
int len = 1 + (int)((end - start) / step); // Include both ends of interval
Double[] result = new Double[len];
Double value = start;
for(int i = 0; i < len; i++, value = start + i*step) {
result[i] = value;
}
return result;
}
public static String [] remove(String [] ary, String s) {
if(s == null)return ary;
int cnt = 0;
int idx = find(ary,s);
while(idx > 0) {
++cnt;
idx = find(ary,s,++idx);
}
if(cnt == 0)return ary;
String [] res = new String[ary.length-cnt];
int j = 0;
for(String x:ary)
if(!x.equals(s))
res[j++] = x;
return res;
}
/*
This class is written to copy the contents of a frame to a 2-D double array.
*/
public static class FrameToArray extends MRTask<FrameToArray> {
int _startColIndex; // first column index to extract
int _endColIndex; // last column index to extract
int _rowNum; // number of columns in
public double[][] _frameContent;
public FrameToArray(int startCol, int endCol, long rowNum, double[][] frameContent) {
assert ((startCol >= 0) && (endCol >= startCol) && (rowNum > 0));
_startColIndex = startCol;
_endColIndex = endCol;
_rowNum = (int) rowNum;
int colNum = endCol-startCol+1;
if (frameContent == null) { // allocate memory here if user has not provided one
_frameContent = MemoryManager.malloc8d(_rowNum, colNum);
} else { // make sure we are passed the correct size 2-D double array
assert (_rowNum == frameContent.length && frameContent[0].length == colNum);
for (int index = 0; index < colNum; index++) { // zero fill use array
Arrays.fill(frameContent[index], 0.0);
}
_frameContent = frameContent;
}
}
@Override public void map(Chunk[] c) {
assert _endColIndex < c.length;
int endCol = _endColIndex+1;
int rowOffset = (int) c[0].start(); // real row index
int chkRows = c[0]._len;
for (int rowIndex = 0; rowIndex < chkRows; rowIndex++) {
for (int colIndex = _startColIndex; colIndex < endCol; colIndex++) {
_frameContent[rowIndex+rowOffset][colIndex-_startColIndex] = c[colIndex].atd(rowIndex);
}
}
}
@Override public void reduce(FrameToArray other) {
ArrayUtils.add(_frameContent, other._frameContent);
}
public double[][] getArray() {
return _frameContent;
}
}
/*
This class is written to a 2-D array to the frame instead of allocating new memory every time.
*/
public static class CopyArrayToFrame extends MRTask<CopyArrayToFrame> {
int _startColIndex; // first column index to extract
int _endColIndex; // last column index to extract
int _rowNum; // number of columns in
public double[][] _frameContent;
public CopyArrayToFrame(int startCol, int endCol, long rowNum, double[][] frameContent) {
assert ((startCol >= 0) && (endCol >= startCol) && (rowNum > 0));
_startColIndex = startCol;
_endColIndex = endCol;
_rowNum = (int) rowNum;
int colNum = endCol-startCol+1;
assert (_rowNum == frameContent.length && frameContent[0].length == colNum);
_frameContent = frameContent;
}
@Override public void map(Chunk[] c) {
assert _endColIndex < c.length;
int endCol = _endColIndex+1;
int rowOffset = (int) c[0].start(); // real row index
int chkRows = c[0]._len;
for (int rowIndex = 0; rowIndex < chkRows; rowIndex++) {
for (int colIndex = _startColIndex; colIndex < endCol; colIndex++) {
c[colIndex].set(rowIndex, _frameContent[rowIndex+rowOffset][colIndex-_startColIndex]);
}
}
}
}
/** Create a new frame based on given row data.
* @param key Key for the frame
* @param names names of frame columns
* @param rows data given in the form of rows
* @return new frame which contains columns named according given names and including given data */
public static Frame frame(Key<Frame> key, String[] names, double[]... rows) {
assert names == null || names.length == rows[0].length;
Futures fs = new Futures();
Vec[] vecs = new Vec[rows[0].length];
Key<Vec>[] keys = Vec.VectorGroup.VG_LEN1.addVecs(vecs.length);
int rowLayout = -1;
for( int c = 0; c < vecs.length; c++ ) {
AppendableVec vec = new AppendableVec(keys[c], Vec.T_NUM);
NewChunk chunk = new NewChunk(vec, 0);
for (double[] row : rows) chunk.addNum(row[c]);
chunk.close(0, fs);
if( rowLayout== -1) rowLayout = vec.compute_rowLayout();
vecs[c] = vec.close(rowLayout,fs);
}
fs.blockForPending();
Frame fr = new Frame(key, names, vecs);
if( key != null ) DKV.put(key, fr);
return fr;
}
public static Frame frame(double[]... rows) { return frame(null, rows); }
public static Frame frame(String[] names, double[]... rows) { return frame(Key.<Frame>make(), names, rows); }
public static Frame frame(String name, Vec vec) { Frame f = new Frame(); f.add(name, vec); return f; }
/**
* Remove b from a, both a,b are assumed to be sorted.
*/
public static int[] removeSorted(int [] a, int [] b) {
int [] indeces = new int[b.length];
indeces[0] = Arrays.binarySearch(a,0,a.length,b[0]);
if(indeces[0] < 0)
throw new NoSuchElementException("value " + b[0] + " not found in the first array.");
for(int i = 1; i < b.length; ++i) {
indeces[i] = Arrays.binarySearch(a,indeces[i-1],a.length,b[i]);
if(indeces[i] < 0)
throw new NoSuchElementException("value " + b[i] + " not found in the first array.");
}
return removeIds(a,indeces);
}
public static int[] removeIds(int[] x, int[] ids) {
int [] res = new int[x.length-ids.length];
int j = 0;
for(int i = 0; i < x.length; ++i)
if(j == ids.length || i != ids[j]) res[i-j] = x[i]; else ++j;
return res;
}
public static double[] removeIds(double[] x, int[] ids) {
double [] res = new double[x.length-ids.length];
int j = 0;
for(int i = 0; i < x.length; ++i)
if(j == ids.length || i != ids[j]) res[i-j] = x[i]; else ++j;
return res;
}
public static boolean hasNzs(double[] x) {
if(x == null)
return false;
for(double d:x)
if(d != 0) return true;
return false;
}
public static int countNonzeros(double[] beta) {
int res = 0;
for(double d:beta)
if(d != 0)++res;
return res;
}
public static long[] subtract(long n, long[] nums) {
for (int i=0; i<nums.length; i++) nums[i] = n - nums[i];
return nums;
}
public static <T> T[] remove( T[] ary, int id) {
if(id < 0 || id >= ary.length) return Arrays.copyOf(ary,ary.length);
if(id == ary.length-1) return Arrays.copyOf(ary,id);
if(id == 0) return Arrays.copyOfRange(ary,1,ary.length);
return append(Arrays.copyOf(ary,id), Arrays.copyOfRange(ary,id+1,ary.length));
}
public static byte[] remove(byte[] ary, int id) {
if(id < 0 || id >= ary.length) return Arrays.copyOf(ary,ary.length);
if(id == ary.length-1) return Arrays.copyOf(ary,id);
if(id == 0) return Arrays.copyOfRange(ary,1,ary.length);
return append(Arrays.copyOf(ary,id), Arrays.copyOfRange(ary,id+1,ary.length));
}
public static int[] remove(int[] ary, int id) {
if(id < 0 || id >= ary.length) return Arrays.copyOf(ary,ary.length);
if(id == ary.length-1) return Arrays.copyOf(ary,id);
if(id == 0) return Arrays.copyOfRange(ary,1,ary.length);
return append(Arrays.copyOf(ary,id), Arrays.copyOfRange(ary,id+1,ary.length));
}
public static long[] remove(long[] ary, int id) {
if(id < 0 || id >= ary.length) return Arrays.copyOf(ary,ary.length);
if(id == ary.length-1) return Arrays.copyOf(ary,id);
if(id == 0) return Arrays.copyOfRange(ary,1,ary.length);
return append(Arrays.copyOf(ary,id), Arrays.copyOfRange(ary,id+1,ary.length));
}
public static double[] padUniformly(double[] origPoints, int newLength) {
int origLength = origPoints.length;
if (newLength <= origLength || origLength<=1) return origPoints;
int extraPoints = newLength - origLength;
int extraPointsPerBin = extraPoints/(origLength-1);
double[] res = new double[newLength];
int pos=0;
int rem = extraPoints - extraPointsPerBin*(origLength-1);
for (int i=0;i<origLength-1;++i) {
double startPos = origPoints[i];
double delta = origPoints[i+1]-startPos;
int ext = extraPointsPerBin + (i<rem ? 1 : 0);
res[pos++] = startPos;
for (int j=0;j<ext;++j)
res[pos++] = startPos + (j+0.5) / ext * delta;
}
res[pos] = origPoints[origLength-1];
return res;
}
// See HistogramTest JUnit for tests
public static double[] makeUniqueAndLimitToRange(double[] splitPoints, double min, double maxEx) {
double last= splitPoints[0];
double[] uniqueValidPoints = new double[splitPoints.length+2];
int count=0;
// keep all unique points that are minimally overlapping with min..maxEx
for (int i = 0; i< splitPoints.length; ++i) {
double pos = splitPoints[i];
// first one
if (pos >= min && count==0) {
uniqueValidPoints[count++]= min;
if (pos> min) uniqueValidPoints[count++]=pos;
last=pos;
}
//last one
else if (pos > maxEx) {
break;
}
// regular case: add to uniques
else if (pos > min && pos < maxEx && (i==0 || pos != last)) {
uniqueValidPoints[count++] = pos;
last = pos;
}
}
if (count==0) {
return new double[]{min};
}
return Arrays.copyOfRange(uniqueValidPoints,0,count);
}
// See HistogramTest JUnit for tests
public static double[] limitToRange(double[] sortedSplitPoints, double min, double maxEx) {
int start=Arrays.binarySearch(sortedSplitPoints, min);
if (start<0) start=-start-1;
// go back one more to return at least one value
if (start==sortedSplitPoints.length) start--;
// go back one more to include the min (inclusive)
if (sortedSplitPoints[start] > min && start>0) start--;
assert(start>=0);
assert(sortedSplitPoints[start] <= min);
int end=Arrays.binarySearch(sortedSplitPoints, maxEx);
if (end<0) end=-end-1;
assert(end>0 && end<= sortedSplitPoints.length);
assert(end>=start);
assert(sortedSplitPoints[end-1] < maxEx);
return Arrays.copyOfRange(sortedSplitPoints,start,end);
}
public static double[] extractCol(int i, double[][] ary) {
double [] res = new double[ary.length];
for(int j = 0; j < ary.length; ++j)
res[j] = ary[j][i];
return res;
}
public static long encodeAsLong(byte[] b) {
return encodeAsLong(b, 0, b.length);
}
public static long encodeAsLong(byte[] b, int off, int len) {
assert len <= 8 : "Cannot encode more then 8 bytes into long: len = " + len;
long r = 0;
int shift = 0;
for(int i = 0; i < len; i++) {
r |= (b[i + off] & 0xFFL) << shift;
shift += 8;
}
return r;
}
public static int encodeAsInt(byte[] b) {
assert b.length == 4 : "Cannot encode more than 4 bytes into int: len = " + b.length;
return (b[0]&0xFF)+((b[1]&0xFF)<<8)+((b[2]&0xFF)<<16)+((b[3]&0xFF)<<24);
}
public static int encodeAsInt(byte[] bs, int at) {
if (at + 4 > bs.length) throw new IndexOutOfBoundsException("Cannot encode more than 4 bytes into int: len = " + bs.length + ", pos=" + at);
return (bs[at]&0xFF)+((bs[at+1]&0xFF)<<8)+((bs[at+2]&0xFF)<<16)+((bs[at+3]&0xFF)<<24);
}
public static byte[] decodeAsInt(int what, byte[] bs, int at) {
if (bs.length < at + 4) throw new IndexOutOfBoundsException("Wrong position " + at + ", array length is " + bs.length);
for (int i = at; i < at+4 && i < bs.length; i++) {
bs[i] = (byte)(what&0xFF);
what >>= 8;
}
return bs;
}
/** Transform given long numbers into byte array.
* Highest 8-bits of the first long will stored in the first field of returned byte array.
*
* Example:
* 0xff18000000000000L -> new byte[] { 0xff, 0x18, 0, 0, 0, 0, 0, 0}
*/
public static byte[] toByteArray(long ...nums) {
if (nums == null || nums.length == 0) return EMPTY_BYTE_ARRAY;
byte[] result = new byte[8*nums.length];
int c = 0;
for (long n : nums) {
for (int i = 0; i < 8; i++) {
result[c*8 + i] = (byte) ((n >>> (56 - 8 * i)) & 0xFF);
}
c++;
}
return result;
}
public static byte[] toByteArray(int[] ary) {
byte[] r = new byte[ary.length];
for (int i = 0; i < ary.length; i++) {
r[i] = (byte) (ary[i] & 0xff);
}
return r;
}
public static boolean equalsAny(long value, long...lhs) {
if (lhs == null || lhs.length == 0) return false;
for (long lhValue : lhs) {
if (value == lhValue) return true;
}
return false;
}
/**
* Convert an array of primitive types into an array of corresponding boxed types. Due to quirks of Java language
* this cannot be done in any generic way -- there should be a separate function for each use case...
* @param arr input array of `char`s
* @return output array of `Character`s
*/
public static Character[] box(char[] arr) {
Character[] res = new Character[arr.length];
for (int i = 0; i < arr.length; i++)
res[i] = arr[i];
return res;
}
/**
* Convert an ArrayList of Integers to a primitive int[] array.
*/
public static int[] toPrimitive(ArrayList<Integer> arr) {
int[] res = new int[arr.size()];
for (int i = 0; i < res.length; i++)
res[i] = arr.get(i);
return res;
}
public static boolean isSorted(int[] vals) {
for (int i = 1; i < vals.length; ++i)
if (vals[i - 1] > vals[i]) return false;
return true;
}
}