
org.numenta.nupic.util.ArrayUtils Maven / Gradle / Ivy
/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2014, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
package org.numenta.nupic.util;
import gnu.trove.list.TDoubleList;
import gnu.trove.list.TIntList;
import gnu.trove.list.array.TDoubleArrayList;
import gnu.trove.list.array.TIntArrayList;
import gnu.trove.map.hash.TDoubleIntHashMap;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* Utilities to match some of the functionality found in Python's Numpy.
* @author David Ray
*/
public class ArrayUtils {
/** Empty array constant */
private static int[] EMPTY_ARRAY = new int[0];
public static Condition WHERE_1 = new Condition.Adapter() {
public boolean eval(int i) {
return i == 1;
}
};
public static Condition GREATER_THAN_0 = new Condition.Adapter() {
public boolean eval(double i) {
return i > 0;
}
};
public static Condition INT_GREATER_THAN_0 = new Condition.Adapter() {
public boolean eval(int i) {
return i > 0;
}
};
public static Condition GREATER_OR_EQUAL_0 = new Condition.Adapter() {
@Override public boolean eval(int n) { return n >= 0; }
};
/**
* Returns the product of each integer in the specified array.
*
* @param dims
* @return
*/
public static int product(int[] dims) {
int retVal = 1;
for(int i = 0;i < dims.length;i++) {
retVal *= dims[i];
}
return retVal;
}
/**
* Returns an array containing the successive elements of each
* argument array as in [ first[0], second[0], first[1], second[1], ... ].
*
* Arrays may be of zero length, and may be of different sizes, but may not be null.
*
* @param first the first array
* @param second the second array
* @return
*/
public static Object[] interleave(F first, S second) {
int flen, slen;
Object[] retVal = new Object[(flen = Array.getLength(first)) + (slen = Array.getLength(second))];
for(int i = 0, j = 0, k = 0;i < flen || j < slen;) {
if(i < flen) {
retVal[k++] = Array.get(first, i++);
}
if(j < slen) {
retVal[k++] = Array.get(second, j++);
}
}
return retVal;
}
/**
* Return a new double[] containing the difference of each element and its
* succeding element.
*
* The first order difference is given by ``out[n] = a[n+1] - a[n]``
* along the given axis, higher order differences are calculated by using `diff`
* recursively.
*
* @param d
* @return
*/
public static double[] diff(double[] d) {
double[] retVal = new double[d.length - 1];
for (int i = 0; i < retVal.length; i++) {
retVal[i] = d[i + 1] - d[i];
}
return retVal;
}
/**
* Returns a flag indicating whether the container list contains an
* array which matches the specified match array.
*
* @param match the array to match
* @param container the list of arrays to test
* @return true if so, false if not
*/
public static boolean contains(int[] match, List container) {
int len = container.size();
for (int i = 0; i < len; i++) {
if (Arrays.equals(match, container.get(i))) {
return true;
}
}
return false;
}
/**
* Returns a new array of size first.length + second.length, with the
* contents of the first array loaded into the returned array starting
* at the zero'th index, and the contents of the second array appended
* to the returned array beginning with index first.length.
*
* This method is fail fast, meaning that it depends on the two arrays
* being non-null, and if not, an exception is thrown.
*
* @param first the data to load starting at index 0
* @param second the data to load starting at index first.length;
* @return a concatenated array
* @throws NullPointerException if either first or second is null
*/
public static double[] concat(double[] first, double[] second) {
double[] retVal = Arrays.copyOf(first, first.length + second.length);
for(int i = first.length, j = 0;i < retVal.length;i++, j++) {
retVal[i] = second[j];
}
return retVal;
}
/**
* Utility to compute a flat index from coordinates.
*
* @param coordinates an array of integer coordinates
* @return a flat index
*/
public static int fromCoordinate(int[] coordinates, int[] shape) {
int[] localMults = initDimensionMultiples(shape);
int base = 0;
for (int i = 0; i < coordinates.length; i++) {
base += (localMults[i] * coordinates[i]);
}
return base;
}
/**
* Utility to compute a flat index from coordinates.
*
* @param coordinates an array of integer coordinates
* @return a flat index
*/
public static int fromCoordinate(int[] coordinates) {
int[] localMults = initDimensionMultiples(coordinates);
int base = 0;
for (int i = 0; i < coordinates.length; i++) {
base += (localMults[i] * coordinates[i]);
}
return base;
}
/**
* Initializes internal helper array which is used for multidimensional
* index computation.
*
* @param dimensions
* @return
*/
public static int[] initDimensionMultiples(int[] dimensions) {
int holder = 1;
int len = dimensions.length;
int[] dimensionMultiples = new int[dimensions.length];
for (int i = 0; i < len; i++) {
holder *= (i == 0 ? 1 : dimensions[len - i]);
dimensionMultiples[len - 1 - i] = holder;
}
return dimensionMultiples;
}
/**
* Returns a string representing an array of 0's and 1's
*
* @param arr an binary array (0's and 1's only)
* @return
*/
public static String bitsToString(int[] arr) {
char[] s = new char[arr.length + 1];
Arrays.fill(s, '.');
s[0] = 'c';
for (int i = 0; i < arr.length; i++) {
if (arr[i] == 1) {
s[i + 1] = '*';
}
}
return new String(s);
}
/**
* Return a list of tuples, where each tuple contains the i-th element
* from each of the argument sequences. The returned list is
* truncated in length to the length of the shortest argument sequence.
*
* @param arg1 the first list to be the zero'th entry in the returned tuple
* @param arg2 the first list to be the one'th entry in the returned tuple
* @return a list of tuples
*/
public static List zip(List> arg1, List> arg2) {
List tuples = new ArrayList();
int len = Math.min(arg1.size(), arg2.size());
for (int i = 0; i < len; i++) {
tuples.add(new Tuple(arg1.get(i), arg2.get(i)));
}
return tuples;
}
/**
* Return a list of tuples, where each tuple contains the i-th element
* from each of the argument sequences. The returned list is
* truncated in length to the length of the shortest argument sequence.
*
* @param arg1 the first list to be the zero'th entry in the returned tuple
* @param arg2 the first list to be the one'th entry in the returned tuple
* @return a list of tuples
*/
public static List zip(Object[]... args) {
List tuples = new ArrayList();
int len = args.length;
for (int i = 0; i < len; i++) {
tuples.add(new Tuple(args[i]));
}
return tuples;
}
/**
* Returns an array with the same shape and the contents
* converted to doubles.
*
* @param ints an array of ints.
* @return
*/
public static double[] toDoubleArray(int[] ints) {
double[] retVal = new double[ints.length];
for (int i = 0; i < ints.length; i++) {
retVal[i] = ints[i];
}
return retVal;
}
/**
* Performs a modulus operation in Python style.
*
* @param a
* @param b
* @return
*/
public static int modulo(int a, int b) {
if (b == 0) throw new IllegalArgumentException("Division by Zero!");
if (a > 0 && b > 0 && b > a) return a;
boolean isMinus = Math.abs(b - (a - b)) < Math.abs(b - (a + b));
if (isMinus) {
while (a >= b) {
a -= b;
}
} else {
if (a % b == 0) return 0;
while (a + b < b) {
a += b;
}
}
return a;
}
/**
* Performs a modulus on every index of the first argument using
* the second argument and places the result in the same index of
* the first argument.
*
* @param a
* @param b
* @return
*/
public static int[] modulo(int[] a, int b) {
for (int i = 0; i < a.length; i++) {
a[i] = modulo(a[i], b);
}
return a;
}
/**
* Returns an array with the same shape and the contents
* converted to integers.
*
* @param doubs an array of doubles.
* @return
*/
public static int[] toIntArray(double[] doubs) {
int[] retVal = new int[doubs.length];
for (int i = 0; i < doubs.length; i++) {
retVal[i] = (int)doubs[i];
}
return retVal;
}
/**
* Returns a double array whose values are the maximum of the value
* in the array and the max value argument.
* @param doubs
* @param maxValue
* @return
*/
public static double[] maximum(double[] doubs, double maxValue) {
double[] retVal = new double[doubs.length];
for (int i = 0; i < doubs.length; i++) {
retVal[i] = Math.max(doubs[i], maxValue);
}
return retVal;
}
/**
* Returns an array of identical shape containing the maximum
* of the values between each corresponding index. Input arrays
* must be the same length.
*
* @param arr1
* @param arr2
* @return
*/
public static int[] maxBetween(int[] arr1, int[] arr2) {
int[] retVal = new int[arr1.length];
for (int i = 0; i < arr1.length; i++) {
retVal[i] = Math.max(arr1[i], arr2[i]);
}
return retVal;
}
/**
* Returns an array of identical shape containing the minimum
* of the values between each corresponding index. Input arrays
* must be the same length.
*
* @param arr1
* @param arr2
* @return
*/
public static int[] minBetween(int[] arr1, int[] arr2) {
int[] retVal = new int[arr1.length];
for (int i = 0; i < arr1.length; i++) {
retVal[i] = Math.min(arr1[i], arr2[i]);
}
return retVal;
}
/**
* Returns an array of values that test true for all of the
* specified {@link Condition}s.
*
* @param values
* @param conditions
* @return
*/
public static int[] retainLogicalAnd(int[] values, Condition>[] conditions) {
TIntArrayList l = new TIntArrayList();
for (int i = 0; i < values.length; i++) {
boolean result = true;
for (int j = 0; j < conditions.length && result; j++) {
result &= conditions[j].eval(values[i]);
}
if (result) l.add(values[i]);
}
return l.toArray();
}
/**
* Returns an array of values that test true for all of the
* specified {@link Condition}s.
*
* @param values
* @param conditions
* @return
*/
public static double[] retainLogicalAnd(double[] values, Condition>[] conditions) {
TDoubleArrayList l = new TDoubleArrayList();
for (int i = 0; i < values.length; i++) {
boolean result = true;
for (int j = 0; j < conditions.length && result; j++) {
result &= conditions[j].eval(values[i]);
}
if (result) l.add(values[i]);
}
return l.toArray();
}
/**
* Returns an array whose members are the quotient of the dividend array
* values and the divisor array values.
*
* @param dividend
* @param divisor
* @param dividend adjustment
* @param divisor adjustment
*
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] divide(double[] dividend, double[] divisor,
double dividendAdjustment, double divisorAdjustment) {
if (dividend.length != divisor.length) {
throw new IllegalArgumentException(
"The dividend array and the divisor array must be the same length");
}
double[] quotient = new double[dividend.length];
double denom = 1;
for (int i = 0; i < dividend.length; i++) {
quotient[i] = (dividend[i] + dividendAdjustment) /
((denom = divisor[i] + divisorAdjustment) == 0 ? 1 : denom); //Protect against division by 0
}
return quotient;
}
/**
* Returns an array whose members are the quotient of the dividend array
* values and the divisor array values.
*
* @param dividend
* @param divisor
* @param dividend adjustment
* @param divisor adjustment
*
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] divide(int[] dividend, int[] divisor) {
if (dividend.length != divisor.length) {
throw new IllegalArgumentException(
"The dividend array and the divisor array must be the same length");
}
double[] quotient = new double[dividend.length];
double denom = 1;
for (int i = 0; i < dividend.length; i++) {
quotient[i] = (dividend[i]) /
(double)((denom = divisor[i]) == 0 ? 1 : denom); //Protect against division by 0
}
return quotient;
}
/**
* Returns an array whose members are the quotient of the dividend array
* values and the divisor value.
*
* @param dividend
* @param divisor
* @param dividend adjustment
* @param divisor adjustment
*
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] divide(double[] dividend, double divisor) {
double[] quotient = new double[dividend.length];
double denom = 1;
for (int i = 0; i < dividend.length; i++) {
quotient[i] = (dividend[i]) /
(double)((denom = divisor) == 0 ? 1 : denom); //Protect against division by 0
}
return quotient;
}
/**
* Returns an array whose members are the quotient of the dividend array
* values and the divisor array values.
*
* @param dividend
* @param divisor
* @param dividend adjustment
* @param divisor adjustment
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] roundDivide(double[] dividend, double[] divisor, int scale) {
if (dividend.length != divisor.length) {
throw new IllegalArgumentException(
"The dividend array and the divisor array must be the same length");
}
double[] quotient = new double[dividend.length];
for (int i = 0; i < dividend.length; i++) {
quotient[i] = (dividend[i]) / (divisor[i] == 0 ? 1 : divisor[i]); //Protect against division by 0
quotient[i] = new BigDecimal(quotient[i]).round(new MathContext(scale, RoundingMode.HALF_UP)).doubleValue();
}
return quotient;
}
/**
* Returns an array whose members are the product of the multiplicand array
* values and the factor array values.
*
* @param multiplicand
* @param factor
* @param multiplicand adjustment
* @param factor adjustment
*
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] multiply(
double[] multiplicand, double[] factor, double multiplicandAdjustment, double factorAdjustment) {
if (multiplicand.length != factor.length) {
throw new IllegalArgumentException(
"The multiplicand array and the factor array must be the same length");
}
double[] product = new double[multiplicand.length];
for (int i = 0; i < multiplicand.length; i++) {
product[i] = (multiplicand[i] + multiplicandAdjustment) * (factor[i] + factorAdjustment);
}
return product;
}
/**
* Returns an array whose members are the product of the multiplicand array
* values and the factor array values.
*
* @param multiplicand
* @param factor
* @param multiplicand adjustment
* @param factor adjustment
*
* @return
* @throws IllegalArgumentException if the two argument arrays are not the same length
*/
public static double[] multiply(double[] multiplicand, int[] factor) {
if (multiplicand.length != factor.length) {
throw new IllegalArgumentException(
"The multiplicand array and the factor array must be the same length");
}
double[] product = new double[multiplicand.length];
for (int i = 0; i < multiplicand.length; i++) {
product[i] = (multiplicand[i]) * (factor[i]);
}
return product;
}
/**
* Returns a new array containing the result of multiplying
* each index of the specified array by the 2nd parameter.
*
* @param array
* @param d
* @return
*/
public static int[] multiply(int[] array, int d) {
int[] product = new int[array.length];
for (int i = 0; i < array.length; i++) {
product[i] = array[i] * d;
}
return product;
}
/**
* Returns a new array containing the result of multiplying
* each index of the specified array by the 2nd parameter.
*
* @param array
* @param d
* @return
*/
public static double[] multiply(double[] array, double d) {
double[] product = new double[array.length];
for (int i = 0; i < array.length; i++) {
product[i] = array[i] * d;
}
return product;
}
/**
* Returns an integer array containing the result of subtraction
* operations between corresponding indexes of the specified arrays.
*
* @param minuend
* @param subtrahend
* @return
*/
public static int[] subtract(int[] minuend, int[] subtrahend) {
int[] retVal = new int[minuend.length];
for (int i = 0; i < minuend.length; i++) {
retVal[i] = minuend[i] - subtrahend[i];
}
return retVal;
}
/**
* Subtracts the contents of the first argument from the last argument's list.
*
* NOTE: Does not destroy/alter the argument lists.
*
* @param minuend
* @param subtrahend
* @return
*/
public static List subtract(List subtrahend, List minuend) {
ArrayList sList = new ArrayList(minuend);
sList.removeAll(subtrahend);
return new ArrayList(sList);
}
/**
* Returns the average of all the specified array contents.
* @param arr
* @return
*/
public static double average(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum / (double)arr.length;
}
/**
* Returns the average of all the specified array contents.
* @param arr
* @return
*/
public static double average(double[] arr) {
double sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum / (double)arr.length;
}
/**
* Computes and returns the variance.
* @param arr
* @param mean
* @return
*/
public static double variance(double[] arr, double mean) {
double accum = 0.0;
double dev = 0.0;
double accum2 = 0.0;
for (int i = 0; i < arr.length; i++) {
dev = arr[i] - mean;
accum += dev * dev;
accum2 += dev;
}
double var = (accum - (accum2 * accum2 / arr.length)) / arr.length;
return var;
}
/**
* Computes and returns the variance.
* @param arr
* @return
*/
public static double variance(double[] arr) {
return variance(arr, average(arr));
}
/**
* Returns the passed in array with every value being altered
* by the addition of the specified amount.
*
* @param arr
* @param amount
* @return
*/
public static int[] add(int[] arr, int amount) {
for (int i = 0; i < arr.length; i++) {
arr[i] += amount;
}
return arr;
}
/**
* Returns the passed in array with every value being altered
* by the addition of the specified double amount at the same
* index
*
* @param arr
* @param amount
* @return
*/
public static int[] i_add(int[] arr, int[] amount) {
for (int i = 0; i < arr.length; i++) {
arr[i] += amount[i];
}
return arr;
}
/**
* Returns the passed in array with every value being altered
* by the addition of the specified double amount at the same
* index
*
* @param arr
* @param amount
* @return
*/
public static double[] d_add(double[] arr, double[] amount) {
for (int i = 0; i < arr.length; i++) {
arr[i] += amount[i];
}
return arr;
}
/**
* Returns the passed in array with every value being altered
* by the addition of the specified double amount
*
* @param arr
* @param amount
* @return
*/
public static double[] d_add(double[] arr, double amount) {
for (int i = 0; i < arr.length; i++) {
arr[i] += amount;
}
return arr;
}
/**
* Returns the sum of all contents in the specified array.
* @param array
* @return
*/
public static int sum(int[] array) {
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
return sum;
}
/**
* Test whether each element of a 1-D array is also present in a second
* array.
*
* Returns a int array whose length is the number of intersections.
*
* @param ar1 the array of values to find in the second array
* @param ar2 the array to test for the presence of elements in the first array.
* @return an array containing the intersections or an empty array if none are found.
*/
public static int[] in1d(int[] ar1, int[] ar2) {
if(ar1 == null || ar2 == null) {
return EMPTY_ARRAY;
}
TIntSet retVal = new TIntHashSet(ar2);
retVal.retainAll(ar1);
return retVal.toArray();
}
/**
* Returns the sum of all contents in the specified array.
* @param array
* @return
*/
public static double sum(double[] array) {
double sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
return sum;
}
/**
* Sparse or due to the arrays containing the indexes of "on bits",
* the or of which is equal to the mere combination of the two
* arguments - eliminating duplicates and sorting.
*
* @param arg1
* @param arg2
* @return
*/
public static int[] sparseBinaryOr(int[] arg1, int[] arg2) {
TIntArrayList t = new TIntArrayList(arg1);
t.addAll(arg2);
return unique(t.toArray());
}
/**
* Prints the specified array to a returned String.
*
* @param aObject the array object to print.
* @return the array in string form suitable for display.
*/
public static String print1DArray(Object aObject) {
if (aObject.getClass().isArray()) {
if (aObject instanceof Object[]) // can we cast to Object[]
{
return Arrays.toString((Object[])aObject);
} else { // we can't cast to Object[] - case of primitive arrays
int length = Array.getLength(aObject);
Object[] objArr = new Object[length];
for (int i = 0; i < length; i++)
objArr[i] = Array.get(aObject, i);
return Arrays.toString(objArr);
}
}
return "[]";
}
/**
* Another utility to account for the difference between Python and Java.
* Here the modulo operator is defined differently.
*
* @param n
* @param divisor
* @return
*/
public static double positiveRemainder(double n, double divisor) {
if (n >= 0) {
return n % divisor;
} else {
double val = divisor + (n % divisor);
return val == divisor ? 0 : val;
}
}
/**
* Returns an array which starts from lowerBounds (inclusive) and
* ends at the upperBounds (exclusive).
*
* @param lowerBounds
* @param upperBounds
* @return
*/
public static int[] range(int lowerBounds, int upperBounds) {
TIntList ints = new TIntArrayList();
for (int i = lowerBounds; i < upperBounds; i++) {
ints.add(i);
}
return ints.toArray();
}
/**
* Returns an array which starts from lowerBounds (inclusive) and
* ends at the upperBounds (exclusive).
*
* @param lowerBounds the starting value
* @param upperBounds the maximum value (exclusive)
* @param interval the amount by which to increment the values
* @return
*/
public static double[] arange(double lowerBounds, double upperBounds, double interval) {
TDoubleList doubs = new TDoubleArrayList();
for (double i = lowerBounds; i < upperBounds; i += interval) {
doubs.add(i);
}
return doubs.toArray();
}
/**
* Returns a sorted unique array of integers
*
* @param nums an unsorted array of integers with possible duplicates.
* @return
*/
public static int[] unique(int[] nums) {
TIntHashSet set = new TIntHashSet(nums);
int[] result = set.toArray();
Arrays.sort(result);
return result;
}
/**
* Helper Class for recursive coordinate assembling
*/
private static class CoordinateAssembler {
final private int[] position;
final private List dimensions;
final List result = new ArrayList();
public static List assemble(List dimensions) {
CoordinateAssembler assembler = new CoordinateAssembler(dimensions);
assembler.process(dimensions.size());
return assembler.result;
}
private CoordinateAssembler(List dimensions) {
this.dimensions = dimensions;
position = new int[dimensions.size()];
}
private void process(int level) {
if (level == 0) {// terminating condition
int[] coordinates = new int[position.length];
System.arraycopy(position, 0, coordinates, 0, position.length);
result.add(coordinates);
} else {// inductive condition
int index = dimensions.size() - level;
int[] currentDimension = dimensions.get(index);
for (int i = 0; i < currentDimension.length; i++) {
position[index] = currentDimension[i];
process(level - 1);
}
}
}
}
/**
* Called to merge a list of dimension arrays into a sequential row-major indexed
* list of coordinates.
*
* @param dimensions a list of dimension arrays, each array being a dimension
* of an n-dimensional array.
* @return a list of n-dimensional coordinates in row-major format.
*/
public static List dimensionsToCoordinateList(List dimensions) {
return CoordinateAssembler.assemble(dimensions);
}
/**
* Sets the values in the specified values array at the indexes specified,
* to the value "setTo".
*
* @param values the values to alter if at the specified indexes.
* @param indexes the indexes of the values array to alter
* @param setTo the value to set at the specified indexes.
*/
public static void setIndexesTo(double[] values, int[] indexes, double setTo) {
for (int i = 0; i < indexes.length; i++) {
values[indexes[i]] = setTo;
}
}
/**
* Sets the values in the specified values array at the indexes specified,
* to the value "setTo".
*
* @param values the values to alter if at the specified indexes.
* @param indexes the indexes of the values array to alter
* @param setTo the value to set at the specified indexes.
*/
public static void setIndexesTo(int[] values, int[] indexes, int setTo) {
for (int i = 0; i < indexes.length; i++) {
values[indexes[i]] = setTo;
}
}
/**
* Sets the values in range start to stop to the value specified. If
* stop < 0, then stop indicates the number of places counting from the
* length of "values" back.
*
* @param values the array to alter
* @param start the start index (inclusive)
* @param stop the end index (exclusive)
* @param setTo the value to set the indexes to
*/
public static void setRangeTo(int[] values, int start, int stop, int setTo) {
stop = stop < 0 ? values.length + stop : stop;
for (int i = start; i < stop; i++) {
values[i] = setTo;
}
}
/**
* Returns a random, sorted, and unique array of the specified sample size of
* selections from the specified list of choices.
*
* @param sampleSize the number of selections in the returned sample
* @param choices the list of choices to select from
* @param random a random number generator
* @return a sample of numbers of the specified size
*/
public static int[] sample(int sampleSize, TIntArrayList choices, Random random) {
TIntHashSet temp = new TIntHashSet();
int upperBound = choices.size();
for (int i = 0; i < sampleSize; i++) {
int randomIdx = random.nextInt(upperBound);
while (temp.contains(choices.get(randomIdx))) {
randomIdx = random.nextInt(upperBound);
}
temp.add(choices.get(randomIdx));
}
TIntArrayList al = new TIntArrayList(temp);
al.sort();
return al.toArray();
}
/**
* Returns a double[] filled with random doubles of the specified size.
* @param sampleSize
* @param random
* @return
*/
public static double[] sample(int sampleSize, Random random) {
double[] sample = new double[sampleSize];
for (int i = 0; i < sampleSize; i++) {
sample[i] = random.nextDouble();
}
return sample;
}
/**
* Ensures that each entry in the specified array has a min value
* equal to or greater than the specified min and a maximum value less
* than or equal to the specified max.
*
* @param values the values to clip
* @param min the minimum value
* @param max the maximum value
*/
public static double[] clip(double[] values, double min, double max) {
for (int i = 0; i < values.length; i++) {
values[i] = Math.min(1, Math.max(0, values[i]));
}
return values;
}
/**
* Ensures that each entry in the specified array has a min value
* equal to or greater than the min at the specified index and a maximum value less
* than or equal to the max at the specified index.
*
* @param values the values to clip
* @param min the minimum value
* @param max the maximum value
*/
public static int[] clip(int[] values, int[] min, int[] max) {
for (int i = 0; i < values.length; i++) {
values[i] = Math.max(min[i], Math.min(max[i], values[i]));
}
return values;
}
/**
* Ensures that each entry in the specified array has a min value
* equal to or greater than the min at the specified index and a maximum value less
* than or equal to the max at the specified index.
*
* @param values the values to clip
* @param max the minimum value
* @param adj the adjustment amount
*/
public static int[] clip(int[] values, int[] max, int adj) {
for (int i = 0; i < values.length; i++) {
values[i] = Math.max(0, Math.min(max[i] + adj, values[i]));
}
return values;
}
/**
* Returns the count of values in the specified array that are
* greater than the specified compare value
*
* @param compare the value to compare to
* @param array the values being compared
*
* @return the count of values greater
*/
public static int valueGreaterCount(double compare, double[] array) {
int count = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] > compare) {
count++;
}
}
return count;
}
/**
* Returns the count of values in the specified array that are
* greater than the specified compare value
*
* @param compare the value to compare to
* @param array the values being compared
*
* @return the count of values greater
*/
public static int valueGreaterCountAtIndex(double compare, double[] array, int[] indexes) {
int count = 0;
for (int i = 0; i < indexes.length; i++) {
if (array[indexes[i]] > compare) {
count++;
}
}
return count;
}
/**
* Returns an array containing the n greatest values.
* @param array
* @param n
* @return
*/
public static int[] nGreatest(double[] array, int n) {
TDoubleIntHashMap places = new TDoubleIntHashMap();
int i;
double key;
for (int j = 1; j < array.length; j++) {
key = array[j];
for (i = j - 1; i >= 0 && array[i] < key; i--) {
array[i + 1] = array[i];
}
array[i + 1] = key;
places.put(key, j);
}
int[] retVal = new int[n];
for (i = 0; i < n; i++) {
retVal[i] = places.get(array[i]);
}
return retVal;
}
/**
* Raises the values in the specified array by the amount specified
* @param amount the amount to raise the values
* @param values the values to raise
*/
public static void raiseValuesBy(double amount, double[] values) {
for (int i = 0; i < values.length; i++) {
values[i] += amount;
}
}
/**
* Raises the values at the indexes specified by the amount specified.
* @param amount the amount to raise the values
* @param values the values to raise
*/
public static void raiseValuesBy(double amount, double[] values, int[] indexesToRaise) {
for (int i = 0; i < indexesToRaise.length; i++) {
values[indexesToRaise[i]] += amount;
}
}
/**
* Raises the values at the indexes specified by the amount specified.
* @param amount the amount to raise the values
* @param values the values to raise
*/
public static void raiseValuesBy(double[] amounts, double[] values) {
for (int i = 0; i < values.length; i++) {
values[i] += amounts[i];
}
}
/**
* Raises the values at the indicated indexes, by the amount specified
*
* @param amount
* @param indexes
* @param values
*/
public static void raiseValuesBy(int amount, int[] indexes, int[] values) {
for (int i = 0; i < indexes.length; i++) {
values[indexes[i]] += amount;
}
}
/**
* Scans the specified values and applies the {@link Condition} to each
* value, returning the indexes of the values where the condition evaluates
* to true.
*
* @param values the values to test
* @param c the condition used to test each value
* @return
*/
public static int[] where(double[] d, Condition c) {
TIntArrayList retVal = new TIntArrayList();
int len = d.length;
for (int i = 0; i < len; i++) {
if (c.eval(d[i])) {
retVal.add(i);
}
}
return retVal.toArray();
}
/**
* Scans the specified values and applies the {@link Condition} to each
* value, returning the indexes of the values where the condition evaluates
* to true.
*
* @param values the values to test
* @param c the condition used to test each value
* @return
*/
public static int[] where(int[] d, Condition c) {
TIntArrayList retVal = new TIntArrayList();
int len = d.length;
for (int i = 0; i < len; i++) {
if (c.eval(d[i])) {
retVal.add(i);
}
}
return retVal.toArray();
}
/**
* Returns a flag indicating whether the specified array
* is a sparse array of 0's and 1's or not.
*
* @param ia
* @return
*/
public static boolean isSparse(int[] ia) {
for(int i = ia.length - 1;i >= 0;i--) {
if(ia[i] > 1) return true;
}
return false;
}
/**
* Returns a bit vector of the specified size whose "on" bit
* indexes are specified in "in"; basically converting a sparse
* array to a dense one.
*
* @param in the sparse array specifying the on bits of the returned array
* @param size the size of the dense array to be returned.
* @return
*/
public static int[] asDense(int[] in, int size) {
int[] retVal = new int[size];
Arrays.stream(in).forEach(i -> {retVal[i] = 1;});
return retVal;
}
/**
* Scans the specified values and applies the {@link Condition} to each
* value, returning the indexes of the values where the condition evaluates
* to true.
*
* @param values the values to test
* @param c the condition used to test each value
* @return
*/
public static int[] where(List l, Condition c) {
TIntArrayList retVal = new TIntArrayList();
int len = l.size();
for (int i = 0; i < len; i++) {
if (c.eval(l.get(i))) {
retVal.add(i);
}
}
return retVal.toArray();
}
/**
* Scans the specified values and applies the {@link Condition} to each
* value, returning the indexes of the values where the condition evaluates
* to true.
*
* @param values the values to test
* @param c the condition used to test each value
* @return
*/
public static int[] where(T[] t, Condition c) {
TIntArrayList retVal = new TIntArrayList();
for (int i = 0; i < t.length; i++) {
if (c.eval(t[i])) {
retVal.add(i);
}
}
return retVal.toArray();
}
/**
* Makes all values in the specified array which are less than or equal to the specified
* "x" value, equal to the specified "y".
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void lessThanOrEqualXThanSetToY(double[] array, double x, double y) {
for (int i = 0; i < array.length; i++) {
if (array[i] <= x) array[i] = y;
}
}
/**
* Makes all values in the specified array which are less than the specified
* "x" value, equal to the specified "y".
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void lessThanXThanSetToY(double[] array, double x, double y) {
for (int i = 0; i < array.length; i++) {
if (array[i] < x) array[i] = y;
}
}
/**
* Makes all values in the specified array which are less than the specified
* "x" value, equal to the specified "y".
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void lessThanXThanSetToY(int[] array, int x, int y) {
for (int i = 0; i < array.length; i++) {
if (array[i] < x) array[i] = y;
}
}
/**
* Makes all values in the specified array which are greater than or equal to the specified
* "x" value, equal to the specified "y".
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void greaterThanOrEqualXThanSetToY(double[] array, double x, double y) {
for (int i = 0; i < array.length; i++) {
if (array[i] >= x) array[i] = y;
}
}
/**
* Makes all values in the specified array which are greater than the specified
* "x" value, equal to the specified "y".
*
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void greaterThanXThanSetToY(double[] array, double x, double y) {
for (int i = 0; i < array.length; i++) {
if (array[i] > x) array[i] = y;
}
}
/**
* Makes all values in the specified array which are greater than the specified
* "x" value, equal to the specified "y".
* @param array
* @param x the comparison
* @param y the value to set if the comparison fails
*/
public static void greaterThanXThanSetToY(int[] array, int x, int y) {
for (int i = 0; i < array.length; i++) {
if (array[i] > x) array[i] = y;
}
}
/**
* Returns the index of the max value in the specified array
* @param array the array to find the max value index in
* @return the index of the max value
*/
public static int argmax(int[] array) {
int index = -1;
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
index = i;
}
}
return index;
}
/**
* Returns the index of the max value in the specified array
* @param array the array to find the max value index in
* @return the index of the max value
*/
public static int argmax(double[] array) {
int index = -1;
double max = Double.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
index = i;
}
}
return index;
}
/**
* Returns the maximum value in the specified array
* @param array
* @return
*/
public static int max(int[] array) {
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns the maximum value in the specified array
* @param array
* @return
*/
public static double max(double[] array) {
double max = Double.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
return max;
}
/**
* Returns a new array containing the items specified from
* the source array by the indexes specified.
*
* @param source
* @param indexes
* @return
*/
public static double[] sub(double[] source, int[] indexes) {
double[] retVal = new double[indexes.length];
for (int i = 0; i < indexes.length; i++) {
retVal[i] = source[indexes[i]];
}
return retVal;
}
/**
* Returns a new array containing the items specified from
* the source array by the indexes specified.
*
* @param source
* @param indexes
* @return
*/
public static int[] sub(int[] source, int[] indexes) {
int[] retVal = new int[indexes.length];
for (int i = 0; i < indexes.length; i++) {
retVal[i] = source[indexes[i]];
}
return retVal;
}
/**
* Returns a new 2D array containing the items specified from
* the source array by the indexes specified.
*
* @param source
* @param indexes
* @return
*/
public static int[][] sub(int[][] source, int[] indexes) {
int[][] retVal = new int[indexes.length][];
for (int i = 0; i < indexes.length; i++) {
retVal[i] = source[indexes[i]];
}
return retVal;
}
/**
* Returns the minimum value in the specified array
* @param array
* @return
*/
public static int min(int[] array) {
int min = Integer.MAX_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns the minimum value in the specified array
* @param array
* @return
*/
public static double min(double[] array) {
double min = Double.MAX_VALUE;
for (int i = 0; i < array.length; i++) {
if (array[i] < min) {
min = array[i];
}
}
return min;
}
/**
* Returns a copy of the specified integer array in
* reverse order
*
* @param d
* @return
*/
public static int[] reverse(int[] d) {
int[] ret = new int[d.length];
for (int i = 0, j = d.length - 1; j >= 0; i++, j--) {
ret[i] = d[j];
}
return ret;
}
/**
* Returns a copy of the specified double array in
* reverse order
*
* @param d
* @return
*/
public static double[] reverse(double[] d) {
double[] ret = new double[d.length];
for (int i = 0, j = d.length - 1; j >= 0; i++, j--) {
ret[i] = d[j];
}
return ret;
}
/**
* Returns a new int array containing the or'd on bits of
* both arg1 and arg2.
*
* @param arg1
* @param arg2
* @return
*/
public static int[] or(int[] arg1, int[] arg2) {
int[] retVal = new int[Math.max(arg1.length, arg2.length)];
for (int i = 0; i < arg1.length; i++) {
retVal[i] = arg1[i] > 0 || arg2[i] > 0 ? 1 : 0;
}
return retVal;
}
/**
* Returns a new int array containing the and'd bits of
* both arg1 and arg2.
*
* @param arg1
* @param arg2
* @return
*/
public static int[] and(int[] arg1, int[] arg2) {
int[] retVal = new int[Math.max(arg1.length, arg2.length)];
for (int i = 0; i < arg1.length; i++) {
retVal[i] = arg1[i] > 0 && arg2[i] > 0 ? 1 : 0;
}
return retVal;
}
/**
* Copies the passed array original into a new array except first element and returns it
*
* @param original the array from which a tail is taken
* @return a new array containing the tail from the original array
*/
public static int[] tail(int[] original) {
return Arrays.copyOfRange(original, 1, original.length);
}
/**
* Set value for array at specified position indexes
*
* @param array
* @param value
* @param indexes
*/
public static void setValue(Object array, int value, int... indexes) {
if (indexes.length == 1) {
((int[])array)[indexes[0]] = value;
} else {
setValue(Array.get(array, indexes[0]), value, tail(indexes));
}
}
/**
*Assigns the specified int value to each element of the specified any dimensional array
* of ints.
* @param array
* @param value
*/
public static void fillArray(Object array, int value) {
if (array instanceof int[]) {
Arrays.fill((int[])array, value);
} else {
for (Object agr : (Object[])array) {
fillArray(agr, value);
}
}
}
/**
* Aggregates all element of multi dimensional array of ints
* @param array
* @return sum of all array elements
*/
public static int aggregateArray(Object array) {
int sum = 0;
if(array instanceof Integer){
return (int)array;
} else if (array instanceof int[]) {
int[] set = (int[])array;
for (int element : set) {
sum += element;
}
return sum;
} else {
for (Object agr : (Object[])array) {
sum += aggregateArray(agr);
}
return sum;
}
}
/**
* Convert multidimensional array to readable String
* @param array
* @return String representation of array
*/
public static String intArrayToString(Object array){
StringBuilder result = new StringBuilder();
if(array instanceof Object[]){
result.append(Arrays.deepToString((Object[]) array));
} else {
//One dimension
result.append(Arrays.toString((int[])array));
}
return result.toString();
}
/**
* Return True if all elements of the values have evaluated to true with condition
* @param values
* @param condition
* @param
* @return
*/
public static boolean all(final int[] values, final Condition condition) {
for (int element : values) {
if (!condition.eval(element)) {
return false;
}
}
return true;
}
/**
* Concat arrays
*
* @return The concatenated array
*
* http://stackoverflow.com/a/784842
*/
@SafeVarargs
public static T[] concatAll(T[] first, T[]... rest) {
int totalLength = first.length;
for (T[] array : rest) {
totalLength += array.length;
}
T[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (T[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
/**
* Concat int arrays
*
* @return The concatenated array
*
* http://stackoverflow.com/a/784842
*/
@SafeVarargs
public static int[] concatAll(int[] first, int[]... rest) {
int totalLength = first.length;
for (int[] array : rest) {
totalLength += array.length;
}
int[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (int[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy