/*
* This code is part of Project Waterloo from King's College London
*
*
* Copyright King's College London 2011-
*
* @author Malcolm Lidierth, King's College London [Contact]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
package kcl.waterloo.math;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Arrays;
/**
* Provides convenience static library for math operations across vectors. Most
* methods are defined for double[] only.
*
* Methods appended with "i" perform operations in-place and so
* over-write the input data by reference.
*
* @author Malcolm Lidierth, King's College London [Contact]
*/
public final class ArrayMath {
/**
* Returns the sum of the elements of the input. Compensates for IEEE
* precision loss.
*
* @param in the input array
* @return a double
*/
public static double sum(double[] in) {
return fp.sum(in);
}
public static double sum(double[] in, int idx0, int idx1) {
return fp.sum(in, idx0, idx1);
}
/**
* Returns the cumulative sum of the elements of the input.
*
* @param in the input array
* @return a double[]
*/
public static double[] cusum(double[] in) {
return fp.cusum(in);
}
/**
* Returns the cumulative y of the elements of the input (in-place).
*
* @param in the input array
* @return a double[]
*/
public static double[] cusumi(double[] in) {
return fp.cusumi(in);
}
/**
* Returns the absolute values for a double[]
*
* @param in the input array
* @return a double[]
*/
public static double[] abs(final double[] in) {
final double[] abs = new double[in.length];
for (int k = 0; k < in.length; k++) {
abs[k] = (in[k] < 0.0) ? -in[k] : (in[k] == 0.0) ? 0.0 : in[k];
}
return abs;
}
/**
* Returns the absolute values for a double[] (in-place)
*
* @param in the input array
* @return a double[]
*/
public static double[] absi(final double[] in) {
for (int k = 0; k < in.length; k++) {
in[k] = (in[k] < 0.0) ? -in[k] : (in[k] == 0.0) ? 0.0 : in[k];
}
return in;
}
/**
* Returns the square roots for a double[]
*
* @param in the input array
* @return a double[]
*/
public static double[] sqrt(final double[] in) {
final double[] sqrt = new double[in.length];
for (int k = 0; k < in.length; k++) {
sqrt[k] = Math.sqrt(in[k]);
}
return sqrt;
}
/**
* Returns the square roots for a double[] (in-place)
*
* @param in the input array
* @return double[]
*/
public static double[] sqrti(final double[] in) {
for (int k = 0; k < in.length; k++) {
in[k] = Math.sqrt(in[k]);
}
return in;
}
/**
* Returns the negated input
*
* @param in the input array
* @return a double[]
*/
public static double[] neg(final double[] in) {
final double[] neg = new double[in.length];
for (int k = 0; k < in.length; k++) {
neg[k] = -in[k];
}
return neg;
}
/**
* Returns the negated input (in-place)
*
* @param in the input array
* @return a double[]
*/
public static double[] negi(final double[] in) {
for (int k = 0; k < in.length; k++) {
in[k] = -in[k];
}
return in;
}
/**
* Returns the Math.log10() for a double[]
*
* @param in the input array
* @return a double[]
*/
public static double[] log10(final double[] in) {
final double[] out = new double[in.length];
for (int k = 0; k < in.length; k++) {
out[k] = Math.log10(in[k]);
}
return out;
}
/**
* Returns the Math.log10() for a double[] (in-place)
*
* @param in the input array
* @return a double[]
*/
public static double[] log10i(final double[] in) {
for (int k = 0; k < in.length; k++) {
in[k] = Math.log10(in[k]);
}
return in;
}
/**
* Returns the Math.pow() for a double[]
*
* @param in the input array
* @param exponent the exponent
* @return a double[]
*/
public static double[] pow(final double[] in, double exponent) {
final double[] out = new double[in.length];
for (int k = 0; k < in.length; k++) {
out[k] = Math.pow(in[k], exponent);
}
return out;
}
/**
* Returns the Math.pow() for a double[] (in-place)
*
* @param in the input array
* @param exponent the exponent
* @return a double[]
*/
public static double[] powi(final double[] in, double exponent) {
for (int k = 0; k < in.length; k++) {
in[k] = Math.pow(in[k], exponent);
}
return in;
}
/**
* Returns the first derivative for a double[]
*
* @param in the input array
* @return a double[]
*/
public static double[] diff(final double[] in) {
final double[] diff = new double[in.length - 1];
for (int k = 0; k < in.length - 1; k++) {
diff[k] = in[k + 1] - in[k];
}
return diff;
}
public static double[] diffpad(final double[] in) {
final double[] diff = new double[in.length];
for (int k = 0; k < in.length - 1; k++) {
diff[k] = in[k + 1] - in[k];
}
diff[in.length - 1] = Double.NaN;
return diff;
}
/**
* Returns the first derivative for a double[] (in-place). The final element
* will be set to NaN.
*
* @param in the input array
* @return a double[]
*/
public static double[] diffi(final double[] in) {
for (int k = 0; k < in.length - 1; k++) {
in[k] = in[k + 1] - in[k];
}
in[in.length - 1] = Double.NaN;
return in;
}
/**
* Fills a double[] of length len, with values beginning with start and
* incrementing by inc. start and inc must be integers Output is reliable
* only for values with a magnitude less than or equal to 2^53
*
* @param len the length of the array to create
* @param start the starting value
* @param inc the increment between elements
* @return a double[]
*/
public static double[] fill(int len, int start, int inc) {
final double[] fill = new double[len];
for (int k = 0; k < len; k++) {
fill[k] = start + (k * inc);
}
return fill;
}
/**
* Fills the input with the specified value (in-place)
*
* @param in the input array
* @param constant the constant value to fill the array with
* @return a double[]
*/
public static double[] filli(final double[] in, double constant) {
Arrays.fill(in, constant);
return in;
}
/**
* Fills the input with the specified value (in-place)
*
* @param in the input array
* @param constant the constant value to fill the array with
* @return a boolean[]
*/
public static boolean[] filli(final boolean[] in, boolean constant) {
Arrays.fill(in, constant);
return in;
}
/**
* Returns in1/in2 element-wise where in1 and in2 are double[]s
*
* @param in1 the numerator array
* @param in2 the divisor array
* @return a double[] the returned array
*/
public static double[] div(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
final double[] div = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
div[k] = in1[k] / in2[k];
}
return div;
}
/**
* Returns in1/in2 element-wise where in1 and in2 are double[]s (in-place)
*
* @param in1 the numerator array
* @param in2 the divisor array
* @return a double[] the returned array (i.e. the numerator array)
*/
public static double[] divi(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] = in1[k] / in2[k];
}
return in1;
}
/**
* Returns in1/factor element-wise where in1 is a double[] and factor is
* scalar
*
* @param in1 the numerator array
* @param factor the scalar divisor
* @return a double[] the returned array
*/
public static double[] div(final double[] in1, final double factor) {
final double[] div = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
div[k] = in1[k] / factor;
}
return div;
}
/**
* Returns in1/factor element-wise where in1 is a double[] and factor is
* scalar (in-place)
*
* @param in1 the input array
* @param factor the divisor
* @return a double[] the output array (i.e. in1)
*/
public static double[] divi(final double[] in1, final double factor) {
for (int k = 0; k < in1.length; k++) {
in1[k] = in1[k] / factor;
}
return in1;
}
/**
* Returns factor - in1 element-wise where in1 is a double[] and factor is
* scalar (in-place)
*
* @param in1 the input array
* @param factor the scalar to subtract
* @return a double[] the output array (i.e. in1)
*/
public static double[] subi(final double factor, final double[] in1) {
for (int k = 0; k < in1.length; k++) {
in1[k] = factor - in1[k];
}
return in1;
}
/**
* Returns in1*in2 element-wise where in1 and in2 are double[]s
*
* @param in1 input array 1
* @param in2 input array 2
* @return a double[] the element-wise product
*/
public static double[] mul(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
final double[] mul = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
mul[k] = in1[k] * in2[k];
}
return mul;
}
/**
* Returns in1*in2 element-wise where in1 and in2 are double[]s (in-place)
*
* @param in1 input array 1
* @param in2 input array 2
* @return a double[], the element-wise product (i.e. in1)
*/
public static double[] muli(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] *= in2[k];
}
return in1;
}
/**
* Returns in1*factor element-wise where in1 is a double[] and factor is
* scalar
*
* @param in1 the input array
* @param factor a scalar factor
* @return a double[] the product
*/
public static double[] mul(final double[] in1, final double factor) {
final double[] mul = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
mul[k] = in1[k] * factor;
}
return mul;
}
/**
* Returns in1*factor element-wise where in1 is a double[] and factor is
* scalar (in-place)
*
* @param in1 the input array
* @param factor a scalar factor
* @return a double[] the product (i.e. in1)
*/
public static double[] muli(final double[] in1, final double factor) {
for (int k = 0; k < in1.length; k++) {
in1[k] *= factor;
}
return in1;
}
/**
* Returns in1+in2 element-wise where in1 and in2 are double[]s
*
* @param in1 input array 1
* @param in2 input array 2
* @return a double[] the sum
*/
public static double[] add(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
final double[] mul = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
mul[k] = in1[k] + in2[k];
}
return mul;
}
/**
* Returns in1+in2 element-wise where in1 and in2 are double[]s
*
* @param in1 input array 1
* @param in2 input array 2
* @return a double[] the sum (i.e. in1)
*/
public static double[] addi(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] += in2[k];
}
return in1;
}
/**
* Returns in1 + factor element-wise
*
* @param in1 the input array
* @param factor the factor to add
* @return a double[] the sum
*/
public static double[] add(final double[] in1, double factor) {
final double[] mul = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
mul[k] = in1[k] + factor;
}
return mul;
}
/**
* Returns in1 + factor element-wise (in-place)
*
* @param in1 the input array
* @param factor the factor to add
* @return a double[] the sum (i.e. in1)
*/
public static double[] addi(final double[] in1, double factor) {
for (int k = 0; k < in1.length; k++) {
in1[k] += factor;
}
return in1;
}
/**
* Returns in1-in2 element-wise where in1 and in2 are double[]s
*
* @param in1 input array 1
* @param in2 input array 2
* @return double[] the difference
*/
public static double[] sub(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
final double[] diff = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
diff[k] = in1[k] - in2[k];
}
return diff;
}
/**
* Returns in1-in2 element-wise where in1 and in2 are double[]s
*
* @param in1 input array 1
* @param in2 input array 2
* @return double[] the difference (i.e. in1)
*/
public static double[] subi(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] -= in2[k];
}
return in1;
}
/**
* Returns in-factor element-wise
*
* @param in input array
* @param factor the value to subtract
* @return double[] the difference (i.e. in1)
*/
public static double[] sub(final double[] in, double factor) {
final double[] diff = new double[in.length];
for (int k = 0; k < in.length; k++) {
diff[k] = in[k] - factor;
}
return diff;
}
/**
* Returns in-factor element-wise (in-place)
*
* @param in input array
* @param factor the value to subtract
* @return double[] the difference (i.e. in1)
*/
public static double[] subi(final double[] in, double factor) {
for (int k = 0; k < in.length; k++) {
in[k] -= factor;
}
return in;
}
/**
* Returns scalar dot product of in1 & in2
*
* @param in1 input array 1
* @param in2 input array 2
* @return a double, the dot product of the inputs
*/
public static double dot(final double[] in1, final double[] in2) {
return fp.dot(in1, in2);
}
/**
* Returns true for in==0 (or -0) element-wise
*
* @param in the input array
* @return a boolean[]
*/
public static boolean[] isZero(final double[] in) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] == 0d;
}
return flags;
}
/**
* Returns true for in==x element-wise.
*
* @param in the input array
* @param x the value to compare to
* @return a boolean[]
*/
public static boolean[] isEqual(final double[] in, double x) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] == x;
}
return flags;
}
/**
* Returns true where in has magnitude less than x, element-wise.
*
* @param in the input array
* @param x the value to compare to
* @return a boolean[]
*/
public static boolean[] isLT(final double[] in, double x) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] < x;
}
return flags;
}
/**
* Returns true where in has magnitude less than or equal to x,
* element-wise.
*
* @param in the input array
* @param x the value to compare to
* @return a boolean[]
*/
public static boolean[] isLE(final double[] in, double x) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] <= x;
}
return flags;
}
/**
* Returns true where in is greater than x, element-wise.
*
* @param in the input array
* @param x the value to compare to
* @return a boolean[]
*/
public static boolean[] isGT(final double[] in, double x) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] > x;
}
return flags;
}
/**
* Returns true where in is greater than or equal to x, element-wise.
*
* @param in the input array
* @param x the value to compare to
* @return a boolean[]
*/
public static boolean[] isGE(final double[] in, double x) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = in[k] >= x;
}
return flags;
}
/**
* Returns true where in is Not-a-Number element-wise.
*
* @param in the input array
* @return a boolean[]
*/
public static boolean[] isNaN(final double[] in) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = Double.isNaN(in[k]);
}
return flags;
}
/**
* Returns true where in equals +infinity or -infinity, element-wise.
*
* @param in the input array
* @return a boolean[]
*/
public static boolean[] isInfinite(final double[] in) {
final boolean[] flags = new boolean[in.length];
for (int k = 0; k < in.length; k++) {
flags[k] = (in[k] == Double.POSITIVE_INFINITY
|| in[k] == Double.NEGATIVE_INFINITY);
}
return flags;
}
/**
* Returns true where any element in the input is true
*
* @param in the input array
* @return a boolean
*/
public static boolean any(boolean[] in) {
for (boolean anIn : in) {
if (anIn) {
return true;
}
}
return false;
}
/**
* Returns minimum value ignoring NaNs.
*
* @param in a double[]
* @return the minimum value from the input
*/
public static double min(final double[] in) {
double mn = in[0];
for (int k = 1; k < in.length; k++) {
mn = (in[k] < mn) ? in[k] : mn;
}
return mn;
}
/**
* Returns maximum value ignoring NaNs.
*
* @param in a double[]
* @return the maximum value from the input
*/
public static double max(final double[] in) {
double mx = in[0];
for (double anIn : in) {
mx = (anIn > mx) ? anIn : mx;
}
return mx;
}
/**
* Returns a vector containing the minimum for each element from the inputs.
* NaNs will always be judged greater than any other value.
*
* @param in1 input array 1
* @param in2 input array 2
* @return the minimum values from the inputs
*/
public static double[] min(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
double[] out = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
out[k] = Math.min(in1[k], in2[k]);
}
return out;
}
/**
* Returns a vector containing the minimum for each element from the inputs.
* NaNs will always be judged greater than any other value. In-place
* operation: the output will be put into the first input vector. (in-place)
*
* @param in1 input array 1
* @param in2 input array 2
* @return the minimum values from the inputs (in in1)
*/
public static double[] mini(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] = Math.min(in1[k], in2[k]);
}
return in1;
}
/**
* Returns a vector containing the minimum for each element from the input
* and the factor supplied.
*
* @param in input array
* @param factor to comapre the input to
* @return the minimum values from the input and factor (in in1)
*/
public static double[] min(final double[] in, final double factor) {
double[] out = new double[in.length];
for (int k = 0; k < in.length; k++) {
out[k] = Math.min(in[k], factor);
}
return out;
}
/**
* Returns a vector containing the maximum for each element from the input
* and the factor supplied.
*
* @param in input array
* @param factor to compare to
* @return the maximum values from the input and factor
*/
public static double[] max(final double[] in, final double factor) {
double[] out = new double[in.length];
for (int k = 0; k < in.length; k++) {
out[k] = Math.max(in[k], factor);
}
return out;
}
/**
* Returns a vector containing the maximum for each element from the inputs.
* DOES NOT ignore NaNs which will be judged larger than any other value.
*
* @param in1 input array 1
* @param in2 input array 2
* @return the maximum values from the inputs
*/
public static double[] max(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
double[] out = new double[in1.length];
for (int k = 0; k < in1.length; k++) {
out[k] = Math.max(in1[k], in2[k]);
}
return out;
}
/**
* Returns a vector containing the maximum for each element from the inputs.
* DOES NOT ignore NaNs which will be judged larger than any other value.
* (in-place)
*
* @param in1 input array 1
* @param in2 input array 2
* @return the maximum values from the inputs (in in1)
*/
public static double[] maxi(final double[] in1, final double[] in2) {
assertSameLength(in1, in2);
for (int k = 0; k < in1.length; k++) {
in1[k] = Math.max(in1[k], in2[k]);
}
return in1;
}
/**
* Returns a vector containing the maximum for each element from the input
* and factor. DOES NOT ignore NaNs which will be judged larger than any
* other value (in-place).
*
* @param in1 input array 1
* @param factor
* @return the maximum values from the input and factor (in in1)
*/
public static double[] maxi(final double[] in1, final double factor) {
for (int k = 0; k < in1.length; k++) {
in1[k] = Math.max(in1[k], factor);
}
return in1;
}
/**
* Returns a vector containing the minimum for each element from the inputs.
* DOES NOT ignore NaNs which will be judged larger than any other value.
*
* @param in1 input array 1
* @param factor a scalar value
* @return the minimum values
*/
public static double[] mini(final double[] in1, final double factor) {
for (int k = 0; k < in1.length; k++) {
in1[k] = Math.min(in1[k], factor);
}
return in1;
}
/**
* Returns double[2] array containing the minimum and maximum values
* ignoring NaNs.
*
* @param in a double[]
* @return the minimum & maximum value from the input
*/
public static double[] minmax(final double[] in) {
double mx = in[0];
double mn = in[0];
for (int k = 1; k < in.length; k++) {
mx = (in[k] > mx) ? in[k] : mx;
mn = (in[k] < mn) ? in[k] : mn;
}
return new double[]{mn, mx};
}
/**
* Returns int[2] array containing the minimum and maximum values ignoring
* NaNs.
*
* @param in a int[]
* @return the minimum & maximum value from the input
*/
public static int[] minmax(final int[] in) {
int mx = in[0];
int mn = in[0];
for (int k = 1; k < in.length; k++) {
mx = (in[k] > mx) ? in[k] : mx;
mn = (in[k] < mn) ? in[k] : mn;
}
return new int[]{mn, mx};
}
/**
* Repetitively fills the vector in with the values from vec
*
* @param in the array to fill
* @param vec the source values
* @return the returned repeated vector
*/
public double[] repVeci(final double[] in, double[] vec) {
for (int k = 0; k < in.length; k++) {
in[k] = vec[k % vec.length];
}
return in;
}
public static double[] linspace(double start, double stop, int n) {
BigDecimal lim0 = new BigDecimal(start, MathContext.DECIMAL128);
BigDecimal lim1 = new BigDecimal(stop, MathContext.DECIMAL128);
BigDecimal step = lim1.subtract(lim0, MathContext.DECIMAL128);
step = step.divide(new BigDecimal(Double.valueOf((double) n - 1)), MathContext.DECIMAL128);
double[] darr = new double[n];
darr[0] = lim0.doubleValue();
for (int k = 1; k < darr.length; k++) {
lim0 = lim0.add(step);
darr[k] = lim0.doubleValue();
}
return darr;
}
private static void assertSameLength(double[] X, double[] Y) {
if (X.length != Y.length) {
throw new ArrayIndexOutOfBoundsException(
"Vectors must be the same length: not " + X.length + " and " + Y.length);
}
}
}
Ads help maintain this website.