/*
 This file is part of the software framework JStatCom, 
 a library for building applications for data based analysis.

 Copyright (C) 2000-2005  Markus Kraetzig

 This library 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 2.1 of the
 License, or (at your option) any later version.

 This library 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 library; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA
 */

package com.jstatcom.util;

import java.util.Arrays;

/**
 * A collection of static methods that are related to arrays of numbers. This
 * set of methods contains mainly general array manipulation routines as well as
 * some light-weight mathematical functions.
 * 

* All methods implemented do not modify the original input. Results are always * newly created arrays. If the input is somehow wrong an appropriate exception * is thrown. All methods require that the input arrays have the same number of * elements in each row. * * @author Markus Kraetzig */ public final class UMatrix { /** * Not to be invoked. */ private UMatrix() { } /** * Adds the scalar toAdd to a copy of the array * arg. * * @param arg * the original array * @param toAdd * the number to add to all elements of arg * @return a new array with toAdd added; if * toAdd is NaN, then the resulting * array will contain only NaN's * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[][] add(double[][] arg, double toAdd) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); double[][] m = cloneDoubleArray(arg); for (int i = 0; i < m.length; i++) for (int j = 0; j < m[0].length; j++) m[i][j] += toAdd; return m; } /** * Appends toAppend to the columns of orig and * returns the new merged array. This only works, if orig and * toAppend have the same number of rows. * * @param orig * the array to append the columns of toAppend to * @param toAppend * the arrays to be appended to orig * @return a new array orig~toAppend * @throws IllegalArgumentException * if (orig.length != toAppend.length) or * if (orig == null || toAppend == null) or if * rows of an argument have different lengths */ public static double[][] appendDoubleCols(double[][] orig, double[][] toAppend) { if (orig == null || toAppend == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(orig); checkRowLengths(toAppend); if (orig.length != toAppend.length) throw new IllegalArgumentException( "Different number of rows (orig:" + orig.length + ", toAppend:" + toAppend.length + ")."); int origCols = orig[0].length; int toAppendCols = toAppend[0].length; double[][] newMat = new double[orig.length][origCols + toAppendCols]; for (int i = 0; i < newMat.length; i++) { System.arraycopy(orig[i], 0, newMat[i], 0, origCols); System.arraycopy(toAppend[i], 0, newMat[i], origCols, toAppendCols); } return newMat; } /** * Appends toAppend to the rows of orig and * returns the new merged array. This only works, if orig and * toAppend have the same number of columns. * * @param orig * the array to append the rows of toAppend to * @param toAppend * the arrays to be appended to orig * @return a new array orig|toAppend * @throws IllegalArgumentException * if (orig[0].length != toAppend[0].length) or * if (orig == null || toAppend == null) or if * rows of an argument have different lengths */ public static double[][] appendDoubleRows(double[][] orig, double[][] toAppend) { if (orig == null || toAppend == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(orig); checkRowLengths(toAppend); if (orig.length == 0) return cloneDoubleArray(toAppend); if (toAppend.length == 0) return cloneDoubleArray(orig); if (orig[0].length != toAppend[0].length) throw new IllegalArgumentException( "Different number of columns for appendDoubleRows (orig:" + orig[0].length + ", toAppend:" + toAppend[0].length + ")."); int origRows = orig.length; int toAppendRows = toAppend.length; double[][] newMat = new double[origRows + toAppendRows][]; for (int i = 0; i < origRows; i++) { int l = orig[i].length; double[] arr = new double[l]; System.arraycopy(orig[i], 0, arr, 0, l); newMat[i] = arr; } for (int i = 0; i < toAppendRows; i++) { int l = toAppend[i].length; double[] arr = new double[l]; System.arraycopy(toAppend[i], 0, arr, 0, l); newMat[origRows + i] = arr; } return newMat; } /** * Checks whether all rows of arg have the same number of * columns. If the check fails, an exception is thrown. This is to enforce * the mathematical definition of a matrix. * * @param arg * the double[][] to check * @throws IllegalArgumentException * if the rows of arg have different lengths */ public static void checkRowLengths(double[][] arg) { if (arg != null && arg.length > 0) { int n = arg[0].length; for (int i = 0; i < arg.length; i++) if (arg[i].length != n) throw new IllegalArgumentException( "Rows have different lengths."); } } /** * Checks whether all rows of arg have the same number of * columns. If the check fails, an exception is thrown. This is to enforce * the mathematical definition of a matrix. * * @param arg * the int[][] to check * @throws IllegalArgumentException * if the rows of arg have different lengths */ public static void checkRowLengths(int[][] arg) { if (arg != null && arg.length > 0) { int n = arg[0].length; for (int i = 0; i < arg.length; i++) if (arg[i].length != n) throw new IllegalArgumentException( "Rows have different lengths."); } } /** * Gets an identical copy of x. * * @return the cloned array or *

*/ public static double[][] cloneDoubleArray(double[][] x) { if (x == null) return null; if (x.length == 0 || x[0].length == 0) return new double[0][0]; double[][] y = new double[x.length][]; for (int i = 0; i < x.length; i++) { double[] x_i = x[i]; int l = x_i.length; double[] arr = new double[x[i].length]; System.arraycopy(x_i, 0, arr, 0, l); y[i] = arr; } return y; } /** * Gets an identical copy of x. * * @return the cloned array or * */ public static int[][] cloneIntArray(int[][] x) { if (x == null) return null; if (x.length == 0 || x[0].length == 0) return new int[0][0]; int[][] y = new int[x.length][]; for (int i = 0; i < x.length; i++) { int[] x_i = x[i]; int l = x_i.length; int[] arr = new int[x[i].length]; System.arraycopy(x_i, 0, arr, 0, l); y[i] = arr; } return y; } /** * Compares two double arrays and returns true. if the * dimensions are the same and all elements are equal. If two elements of * arg1 and arg2 are Double.NaN, * they are considered to be equal, whereas arg1, arg2 are * considered to be unequal if at least one of them is null. * * @param arg1 * double array to compare * @param arg2 * double array to compare * @return true if dimensions and all elements are equal or * if arg1, arg2 have both at least one dimension of * zero,
* false otherwise * @throws IllegalArgumentException * if rows of an argument have different lengths */ public static boolean compareDoubleArrays(double[][] arg1, double[][] arg2) { if (arg1 == null || arg2 == null) return false; checkRowLengths(arg1); checkRowLengths(arg2); // Tests whether at least one dimension is 0 in both arguments. if ((arg1.length == 0 || arg1[0].length == 0) && (arg2.length == 0 || arg2[0].length == 0)) return true; if (arg1.length != arg2.length || arg1[0].length != arg2[0].length) return false; for (int i = 0; i < arg1.length; i++) for (int j = 0; j < arg1[0].length; j++) if (Double.doubleToLongBits(arg1[i][j]) != Double .doubleToLongBits(arg2[i][j]) && !(arg1[i][j] == 0 && arg2[i][j] == 0)) return false; return true; } /** * Compares two int arrays and returns true. if the * dimensions are the same and all elements are equal. * * @param arg1 * int array to compare * @param arg2 * int array to compare * @return true if dimensions and all elements are equal or * if arg1, arg2 have both at least one dimension of * zero,
* false otherwise or if at least one argument is * null * @throws IllegalArgumentException * if rows of an argument have different lengths */ public static boolean compareIntArrays(int[][] arg1, int[][] arg2) { if (arg1 == null || arg2 == null) return false; checkRowLengths(arg1); checkRowLengths(arg2); // Tests whether at least one dimension is 0 in both arguments. if ((arg1.length == 0 || arg1[0].length == 0) && (arg2.length == 0 || arg2[0].length == 0)) return true; if (arg1.length != arg2.length || arg1[0].length != arg2[0].length) return false; for (int i = 0; i < arg1.length; i++) for (int j = 0; j < arg1[0].length; j++) if (arg1[i][j] != arg2[i][j]) return false; return true; } /** * Deletes the col colIndex from arg. * * @param arg * the array to delete the col from * @param colIndex * index of the col * @return new double array with the deleted col or * new double[0][0] if the array would be empty * afterwards * @throws IllegalArgumentException * if (arg == null) or * if (colIndex < 0 || arg[0].length < colIndex) * or if (arg.length == 0 || arg[0].length == 0) * or if rows of argument have different lengths */ public static double[][] delCol(double[][] arg, int colIndex) { if (arg == null) throw new IllegalArgumentException("Argument was null."); if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException("Argument was empty."); checkRowLengths(arg); if (colIndex < 0 || arg[0].length <= colIndex) throw new IllegalArgumentException("Bad column index: " + colIndex + "."); if (arg[0].length - 1 == 0) return new double[0][0]; double[][] newArray = new double[arg.length][arg[0].length - 1]; for (int i = 0; i < arg.length; i++) for (int j = 0, k = 0; j < arg[0].length; j++) { if (j != colIndex) newArray[i][k++] = arg[i][j]; } return newArray; } /** * Deletes columns of arg that have been selected by * index and returns a new array with the remaining columns. * A column is selected for deletion if the corresponding index entry is * nonzero. * * @param arg * the array to delete columns from * @param index * the arg[0].length x 1 int array * * @return a new array with the selected columns deleted or * new double[0][0] if all columns where selected for * deletion or if arg.length == 0 * * @throws IllegalArgumentException * if (arg == null || index == null) or * if ((arg.length == 0 || arg[0].length == 0) && index.length > 0) * or if (arg.length == 0 || arg[0].length == 0) * or if rows of argument have different lengths */ public static double[][] delColsIf(double[][] arg, int... index) { if (arg == null || index == null) throw new IllegalArgumentException("Argument was null."); if (index.length == 0 && (arg.length == 0 || arg[0].length == 0)) return new double[0][0]; if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException( "Argument was empty but not index."); checkRowLengths(arg); return selColsIf(arg, flipIndex(index)); } /** * Deletes the row rowIndex from arg. * * @param arg * the array to delete the row from * @param rowIndex * index of the row * @return new double array with the deleted row or * new double[0][0] if the array would be empty * afterwards * @throws IllegalArgumentException * if (arg == null) or * if (rowIndex < 0 || arg.length < rowIndex) * or if (arg.length == 0 || arg[0].length == 0) * or if rows of argument have different lengths */ public static double[][] delRow(double[][] arg, int rowIndex) { if (arg == null) throw new IllegalArgumentException("Argument was null."); if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException("Argument was empty."); checkRowLengths(arg); if (rowIndex < 0 || arg.length <= rowIndex) throw new IllegalArgumentException("Bad row index: " + rowIndex + "."); if (arg.length - 1 == 0 || arg[0].length == 0) return new double[0][0]; double[][] newArray = new double[arg.length - 1][]; for (int i = 0, k = 0; i < arg.length; i++) if (i != rowIndex) { double[] arg_i = arg[i]; int l = arg_i.length; double[] arr = new double[l]; System.arraycopy(arg_i, 0, arr, 0, l); newArray[k++] = arr; } return newArray; } /** * Deletes rows of arg that have been selected by * index and returns a new array with the remaining rows. A * row is selected for deletion if the corresponding index entry is nonzero. * * @param arg * the array to delete rows from * @param index * the arg[0].length x 1 int array * * @return a new array with the selected rows deleted or * new double[0][0] if all rows where selected for * deletion or if arg.length == 0 * * @throws IllegalArgumentException * if (arg == null || index == null) or * if ((arg.length == 0 || arg[0].length == 0) && index.length > 0) * or if (arg.length == 0 || arg[0].length == 0) * or if rows of arg have different lengths */ public static double[][] delRowsIf(double[][] arg, int... index) { if (arg == null || index == null) throw new IllegalArgumentException("Argument was null."); if (index.length == 0 && (arg.length == 0 || arg[0].length == 0)) return new double[0][0]; if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException("Argument was empty."); checkRowLengths(arg); return selRowsIf(arg, flipIndex(index)); } /** * Gets an identity matrix of dimension dim. * * @param dim * the dimension of the quadratic matrix to create * @return the created identity matrix * @throws IllegalArgumentException * if (dim < 0) */ public static double[][] eye(int dim) { if (dim < 0) throw new IllegalArgumentException("Dimension argument " + dim + " < 0."); double[][] d = new double[dim][dim]; for (int i = 0; i < dim; i++) d[i][i] = 1; return d; } /** * Gets a new array with all zero elements of arg set to one * and all nonzero elements set to zero. If arg is a * selection index then this just reverses the selection. * * @param arg * the original index, usually with 1's and 0's, but any values != * 0 are set to 0 * * @return the reversed index or new int[0] if * arg.length == 0 * * @throws IllegalArgumentException * if (arg == null) */ public static int[] flipIndex(int... arg) { if (arg == null) throw new IllegalArgumentException("Argument was null."); int[] reversed = new int[arg.length]; for (int i = 0; i < arg.length; i++) if (arg[i] == 0.0) reversed[i] = 1; return reversed; } /** * Gets a string that contains a printed version of arg. * * @param arg * the array to print * @return a string containing with all elements of arg * @throws IllegalArgumentException * if rows of argument have different lengths */ public static String format(double[][] arg) { checkRowLengths(arg); StringBuffer buffer = new StringBuffer(); buffer.append("rows: " + arg.length + "\n"); if (arg.length > 0) buffer.append("cols: " + arg[0].length + "\n"); for (int i = 0; i < arg.length; i++) { for (int j = 0; j < arg[0].length; j++) buffer.append(new PrintfFormat("%- 13.4f").sprintf(arg[i][j])); buffer.append("\n"); } return buffer.toString(); } /** * Gets the column of the array arg specified with * colIndex. The index starts with 0 as usual. * * @param arg * the array to extract a column from * @param colIndex * the index of the column to extract (starting from 0) * @return a one dimensional double array with the column data * @throws IllegalArgumentException * if (arg == null) or * if (arg.length == 0) or if the index is * outside the valid array bounds or if rows of argument have * different lengths */ public static double[] getDoubleCol(double[][] arg, int colIndex) { if (arg == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(arg); if (arg.length == 0) throw new IllegalArgumentException("Argument has zero rows."); if (colIndex < 0 || colIndex >= arg[0].length) throw new IllegalArgumentException("Invalid index: " + colIndex + "."); double[] result = new double[arg.length]; for (int i = 0; i < result.length; i++) result[i] = arg[i][colIndex]; return result; } /** * Gets the row of the array arg specified with * rowIndex. The index starts with 0 as usual. * * @param arg * the array to extract a row from * @param rowIndex * the index of the row to extract (starting from 0) * @return a one dimensional double array with the row data * @throws IllegalArgumentException * if (arg == null) or * if (arg.length == 0) or if the index is * outside the valid array bounds or if rows of argument have * different lengths */ public static double[] getDoubleRow(double[][] arg, int rowIndex) { if (arg == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(arg); if (arg.length == 0) throw new IllegalArgumentException("Argument has zero rows."); if (rowIndex < 0 || rowIndex >= arg.length) throw new IllegalArgumentException("Invalid index: " + rowIndex + "."); double[] arg_i = arg[rowIndex]; double[] result = new double[arg_i.length]; System.arraycopy(arg_i, 0, result, 0, arg_i.length); return result; } /** * Gets all columns of the array arg defined by * startCol:endCol. The indices start with 0 as usual. * * @param arg * the array to extract columns from * @param startCol * the index of the first column to extract (starting from 0) * @param endCol * the index of the last column to extract (starting from 0) * @return a two dimensional double array with the column data * @throws IllegalArgumentException * if (arg == null) or * if (arg.length == 0) or * if (startCol > endCol) or if the indices * are outside the valid array bounds or if rows of argument * have different lengths */ public static double[][] getDoubleCols(double[][] arg, int startCol, int endCol) { if (arg == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(arg); if (arg.length == 0) throw new IllegalArgumentException("Argument has zero rows."); if (startCol < 0 || startCol >= arg[0].length) throw new IllegalArgumentException("Invalid start index: " + startCol + "."); if (endCol < 0 || endCol >= arg[0].length) throw new IllegalArgumentException("Invalid end index: " + endCol + "."); if (endCol < startCol) throw new IllegalArgumentException("Invalid indices [start:" + startCol + " > end:" + endCol + "]."); int c = endCol - startCol + 1; double[][] newMat = new double[arg.length][c]; for (int i = 0; i < newMat.length; i++) System.arraycopy(arg[i], startCol, newMat[i], 0, c); return newMat; } /** * Gets all rows of the array arg defined by * startRow:endRow. The indices start with 0 as usual. * * @param arg * the array to extract rows from * @param startRow * the index of the first row to extract (starting from 0) * @param endRow * the index of the last row to extract (starting from 0) * @return a two dimensional double array with the row data * @throws IllegalArgumentException * if (arg == null) or * if (arg.length == 0) or * if (startRow > endRow) or if the indices * are outside the valid array bounds or if rows of argument * have different lengths */ public static double[][] getDoubleRows(double[][] arg, int startRow, int endRow) { if (arg == null) throw new IllegalArgumentException("Argument was null."); checkRowLengths(arg); if (arg.length == 0) throw new IllegalArgumentException("Argument has zero rows."); if (startRow < 0 || startRow >= arg.length) throw new IllegalArgumentException("Invalid start index: " + startRow + "."); if (endRow < 0 || endRow >= arg.length) throw new IllegalArgumentException("Invalid end index: " + endRow + "."); if (endRow < startRow) throw new IllegalArgumentException("Invalid indices [start:" + startRow + " > end:" + endRow + "]."); int r = endRow - startRow + 1; double[][] newMat = new double[r][]; System.arraycopy(arg, startRow, newMat, 0, r); return newMat; } /** * Gets the index of the first nonzero element in arg. * * @param arg * the array to check * @return the index of the 1st nonzero element or -1 if there is none * @throws IllegalArgumentException * if (arg == null) */ public static int getFirstNonzeroIndex(double[] arg) { if (arg == null) throw new IllegalArgumentException("Argument was null."); for (int i = 0; i < arg.length; i++) if (arg[i] != 0) return i; return -1; } /** * Gets the index of the last nonzero element in arg. * * @param arg * the array to check * @return the index of the last nonzero element or -1 if there is none * @throws IllegalArgumentException * if (arg == null) */ public static int getLastNonzeroIndex(double[] arg) { if (arg == null) throw new IllegalArgumentException("Argument was null."); for (int i = arg.length - 1; i >= 0; i--) if (arg[i] != 0) return i; return -1; } /** * Gets the number of nonzero elements in arg. * * @param arg * the array to check * @return int the number of elements in arg that are != 0 * @throws IllegalArgumentException * if (arg == null) */ public static int getNonzeroDoubleCount(double[] arg) { if (arg == null) throw new IllegalArgumentException("Argument was null."); int count = 0; for (int i = 0; i < arg.length; i++) if (arg[i] != 0) count++; return count; } /** * Gets the number of nonzero elements in arg. * * @param arg * the array to check, usually an index * @return the number of elements in arg that are != 0 * @throws IllegalArgumentException * if (arg == null) */ public static int getNonzeroIntCount(int[] arg) { if (arg == null) throw new IllegalArgumentException("Argument was null."); int count = 0; for (int i = 0; i < arg.length; i++) if (arg[i] != 0) count++; return count; } /** * Gets a quadratic double array of dimension dim with all * elements on and below the diagonal set to value. * * @param value * the double to store in the lower part of the * array * @param dim * the dimension of the quadratic array * @return a dim x dim lower triangular array * @throws IllegalArgumentException * if (dim < 0), */ public static double[][] lowerTringular(double value, int dim) { if (dim < 0) throw new IllegalArgumentException("Dimension argument " + dim + " < 0."); double[][] triang = new double[dim][dim]; for (int i = 0; i < dim; i++) for (int j = 0; j <= i; j++) triang[i][j] = value; return triang; } /** * Gets a vector with the maxima of all columns of arg. * * @param arg * the original array * @return a arg[0].length vector the maxima of * arg, if a column contains Double.NaN * and other double values, then the smallest double value that is * not a Double.NaN is returned * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] maxc(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0]; double[] m = new double[arg[0].length]; for (int i = 0; i < m.length; i++) { m[i] = arg[0][i]; for (int j = 0; j < arg.length; j++) if (arg[j][i] > m[i] || Double.isNaN(m[i])) m[i] = arg[j][i]; } return m; } /** * Gets a vector with the mean of all columns of arg. * * @param arg * the original array * @return a arg[0].length vector the mean of * arg * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] meanc(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0]; double[] m = sumc(arg); for (int i = 0; i < m.length; i++) m[i] = m[i] / arg.length; return m; } /** * Gets a vector with the minima of all columns of arg. * * @param arg * the original array * @return a arg[0].length vector the minima of * arg, if a column contains Double.NaN * and other double values, then the smallest double value that is * not a Double.NaN is returned * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] minc(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0]; double[] m = new double[arg[0].length]; for (int i = 0; i < m.length; i++) { m[i] = arg[0][i]; for (int j = 0; j < arg.length; j++) if (arg[j][i] < m[i] || Double.isNaN(m[i])) m[i] = arg[j][i]; } return m; } /** * Multiplies the scalar toMult with a copy of the array * arg. * * @param arg * the original array * @param toMult * the number to multiply all elements of arg with * @return a new array multiplied with toMult; if * toMult is NaN, then the resulting * array will contain only NaN's * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[][] multiply(double[][] arg, double toMult) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); double[][] m = cloneDoubleArray(arg); for (int i = 0; i < m.length; i++) for (int j = 0; j < m[0].length; j++) m[i][j] *= toMult; return m; } /** * Gets a double array filled with NaN's. * * @param r * rows of array to create * @param c * cols of array to create * @return the r x c double array filled with NaN's or * new double[0][0] if (r == 0 || c == 0) * @throws IllegalArgumentException * if (r < 0 || c < 0) */ public static double[][] missings(int r, int c) { if (r < 0 || c < 0) throw new IllegalArgumentException("Invalid dimension " + r + ":" + c + " specified."); if (r == 0 || c == 0) return new double[0][0]; double[][] d = new double[r][c]; for (int i = 0; i < r; i++) Arrays.fill(d[i], Double.NaN); return d; } /** * Gets a double array filled with 1's. * * @param r * rows of array to create * @param c * cols of array to create * @return the r x c double array filled with 1's or * new double[0][0] if (r == 0 || c == 0) * @throws IllegalArgumentException * if (r < 0 || c < 0) */ public static double[][] ones(int r, int c) { if (r < 0 || c < 0) throw new IllegalArgumentException("Invalid dimension " + r + ":" + c + " specified."); if (r == 0 || c == 0) return new double[0][0]; double[][] d = new double[r][c]; for (int i = 0; i < r; i++) Arrays.fill(d[i], 1); return d; } /** * Applies Math.pow(arg[i][j], power) to all elements of * arg. * * @param arg * the original array * @param power * the 2nd argument to be applied with Math.pow() * @return a new array with all elements raised to the power of * power * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[][] pow(double[][] arg, double power) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); double[][] m = cloneDoubleArray(arg); for (int i = 0; i < m.length; i++) for (int j = 0; j < m[0].length; j++) m[i][j] = Math.pow(m[i][j], power); return m; } /** * Get the rank of arg. * * @param arg * the array to compute the rank from * @return the rank computed by Jama, 0 * if (arg.length == 0 || arg[0].length == 0) * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static int rank(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return 0; return new Jama.Matrix(arg).rank(); } /** * Gets a double array filled with random numbers generated by * Math.random(). The random numbers are equally distributed * between 0 and 1. * * @param r * rows of array to create * @param c * cols of array to create * @return the r x c double array filled with * Math.random() or * new double[0][0] if (r == 0 || c == 0) * @throws IllegalArgumentException * if (r < 0 || c < 0) */ public static double[][] rndu(int r, int c) { if (r < 0 || c < 0) throw new IllegalArgumentException("Invalid dimension " + r + ":" + c + " specified."); if (r == 0 || c == 0) return new double[0][0]; double[][] d = new double[r][c]; for (int i = 0; i < d.length; i++) for (int j = 0; j < d[0].length; j++) d[i][j] = Math.random(); return d; } /** * Gets all columns of the array arg that have a nonzero * corresponding element in index. * * @param arg * the array to extract columns from * @param index * arg[0].length x 1 vector selecting columns from * arg * * @return new array with the extracted columns, * new double[0][0] if index contains only 0's, a * copy of arg if index contains only * nonzero elements * * @throws IllegalArgumentException * if (arg == null || index == null) or * if ((arg.length == 0 || arg[0].length == 0) && index.length > 0) * or if (arg[0].length != index.length) or if * rows of argument have different lengths */ public static double[][] selColsIf(double[][] arg, int... index) { if (arg == null || index == null) throw new IllegalArgumentException("Argument was null."); if (index.length == 0 && (arg.length == 0 || arg[0].length == 0)) return new double[0][0]; if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException( "Argument was empty but index not."); checkRowLengths(arg); if (arg[0].length != index.length) throw new IllegalArgumentException( "Columns of array do not match with dimension of index (array: " + arg[0].length + ", index: " + index.length + ")."); int num = getNonzeroIntCount(index); // Nothing selected. if (num == 0) return new double[0][0]; // Everything selected. if (num == arg[0].length) return cloneDoubleArray(arg); double[][] ret = new double[arg.length][num]; for (int i = 0, k = 0; i < index.length; i++) if (index[i] != 0.0) { for (int j = 0; j < ret.length; j++) ret[j][k] = arg[j][i]; k++; } return ret; } /** * Gets all rows of the array arg that have a nonzero * corresponding element in index. * * @param arg * the array to extract rows from * @param index * arg.length x 1 vector selecting rows from * arg * * @return new array with the extracted rows, new double[0][0] * if index contains only 0's, a copy of arg if * index contains only nonzero elements * * @throws IllegalArgumentException * if (arg == null || index == null) or * if ((arg.length == 0 || arg[0].length == 0) && index.length > 0) * or if (arg.length != index.length) or if rows * of argument have different lengths */ public static double[][] selRowsIf(double[][] arg, int... index) { if (arg == null || index == null) throw new IllegalArgumentException("Argument was null."); if (index.length == 0 && (arg.length == 0 || arg[0].length == 0)) return new double[0][0]; if (arg.length == 0 || arg[0].length == 0) throw new IllegalArgumentException( "Argument was empty but index not."); checkRowLengths(arg); if (arg.length != index.length) throw new IllegalArgumentException( "Rows of array do not match with dimension of index (array: " + arg.length + ", index: " + index.length + ")."); int num = getNonzeroIntCount(index); // Nothing selected. if (num == 0) return new double[0][0]; // Everything selected. if (num == arg.length) return cloneDoubleArray(arg); double[][] ret = new double[num][arg[0].length]; for (int i = 0, k = 0; i < index.length; i++) if (index[i] != 0.0) { double[] arg_i = arg[i]; double[] arr = new double[arg_i.length]; System.arraycopy(arg_i, 0, arr, 0, arg_i.length); ret[k++] = arr; } return ret; } /** * Gets an array with the sequence of numbers starting from * start being n - 1 times incremented by * increment. * * @param start * the first element of the sequence * @param increment * the difference between two successive elements of the sequence * @param n * the number of elements in the sequence * * @return the sequence as a n x 1 double array * @throws IllegalArgumentException * if (n < 0), or if * start || increment are either * Double.NaN, * Double.NEGATIVE_INFINITY or * Double.POSITIVE_INFINITY, * */ public static double[] seqa(double start, double increment, int n) { if (start == Double.NEGATIVE_INFINITY || start == Double.POSITIVE_INFINITY || Double.isNaN(start)) throw new IllegalArgumentException("Start argument: " + start + " invalid."); if (increment == Double.NEGATIVE_INFINITY || increment == Double.POSITIVE_INFINITY || Double.isNaN(increment)) throw new IllegalArgumentException("Increment argument: " + increment + " invalid."); if (n < 0) throw new IllegalArgumentException("Number argument " + n + " < 0."); double[] d = new double[n]; for (int i = 0; i < n; i++) d[i] = start + i * increment; return d; } /** * Gets a new array with the elements of arg divided by the * standard devitation of the respective columns of arg. * * @param arg * the original array * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[][] standardize(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0][0]; double[] m = stdc(arg); double[][] std = UMatrix.cloneDoubleArray(arg); for (int i = 0; i < std.length; i++) for (int j = 0; j < std[0].length; j++) std[i][j] = std[i][j] / m[j]; return std; } /** * Gets a vector with the standard deviations of all columns of * arg. The standard deviation divisor is * arg.length. * * @param arg * the original array * @return a arg[0].length vector the std. dev. of * arg * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] stdc(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0]; double[] m = meanc(arg); double[] std = new double[m.length]; for (int i = 0; i < std.length; i++) { for (int j = 0; j < arg.length; j++) std[i] += Math.pow(arg[j][i] - m[i], 2); std[i] /= arg.length; std[i] = Math.pow(std[i], 0.5); } return std; } /** * Gets a vector with the sum of all elements in the single columns of * arg. * * @param arg * the original array * @return a arg[0].length vector the column sums of * arg * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] sumc(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0) return new double[0]; double[] m = new double[arg[0].length]; for (int i = 0; i < arg[0].length; i++) for (int j = 0; j < arg.length; j++) m[i] += arg[j][i]; return m; } /** * Transforms an int array into a double * array. This is sometimes needed to prepare arguments for methods that * take double[][] instead of int[][]. * * @param arg * the int array to transform * @return double array or * * @throws IllegalArgumentException * if rows of argument have different lengths */ public static double[][] toDoubleMatrix(int[][] arg) { if (arg == null) return null; checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return new double[0][0]; double[][] m = new double[arg.length][arg[0].length]; for (int i = 0; i < arg.length; i++) for (int j = 0; j < arg[0].length; j++) m[i][j] = arg[i][j]; return m; } /** * Transforms a one-dimensional array into a K x 1 pseudo-two-dimensional * array. This is sometimes needed to prepare arguments for methods that * take double[][] instead of double[]. * * @param arg * the vector-like array to transform * @return two-dimensional array with dimensions arg.length x 1 * or * */ public static double[][] toDoubleMatrix(double[] arg) { if (arg == null) return null; if (arg.length == 0) return new double[0][0]; double[][] m = new double[arg.length][1]; for (int i = 0; i < arg.length; i++) m[i][0] = arg[i]; return m; } /** * Transforms a one-dimensional array into a K x 1 pseudo-two-dimensional * array. This is sometimes needed to prepare arguments for methods that * take double[][] instead of int[]. * * @param arg * the vector-like array to transform * @return two-dimensional array with dimensions arg.length x 1 * or * */ public static double[][] toDoubleMatrix(int[] arg) { if (arg == null) return null; if (arg.length == 0) return new double[0][0]; double[][] m = new double[arg.length][1]; for (int i = 0; i < arg.length; i++) m[i][0] = arg[i]; return m; } /** * Transforms arg into an int array by applying a cast to int * from double to each element of arg. Note that during this * operation information is potentially lost. Only the integer part is * preserved, which is different from rounding. The following special * int values are returned: * * * @param arg * the array to transform * @return two-dimensional int array or * * @throws IllegalArgumentException * if rows of argument have different lengths */ public static int[][] toIntMatrix(double[][] arg) { if (arg == null) return null; checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return new int[0][0]; int[][] m = new int[arg.length][arg[0].length]; for (int i = 0; i < arg.length; i++) for (int j = 0; j < arg[0].length; j++) m[i][j] = (int) arg[i][j]; return m; } /** * Gets a new array which is the transpose arg, which means * that all columns of arg are now the rows of the new array. * * @param arg * the original array * @return the transpose of arg, or * new double[0][0] * if (arg.length == 0 || arg[0].length == 0) * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[][] transpose(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return new double[0][0]; double[][] ret = new double[arg[0].length][arg.length]; for (int i = 0; i < arg.length; i++) for (int j = 0; j < arg[0].length; j++) ret[j][i] = arg[i][j]; return ret; } /** * Get a one dimensional array with to columns of arg stacked * into it. * * @param arg * the array with data * @return a arg.length * arg[0].length x 1 array with the * columns of arg stacked into a vector * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static double[] vec(double[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return new double[0]; double[] res = new double[arg.length * arg[0].length]; for (int j = 0, k = 0; j < arg[0].length; j++) for (int i = 0; i < arg.length; i++) res[k++] = arg[i][j]; return res; } /** * Get a one dimensional array with to columns of arg stacked * into it. * * @param arg * the array with data * @return a arg.length * arg[0].length x 1 array with the * columns of arg stacked into a vector * * @throws IllegalArgumentException * if (arg == null) or if rows of argument have * different lengths */ public static int[] vec(int[][] arg) { if (arg == null) throw new IllegalArgumentException("Array argument was null."); checkRowLengths(arg); if (arg.length == 0 || arg[0].length == 0) return new int[0]; int[] res = new int[arg.length * arg[0].length]; for (int j = 0, k = 0; j < arg[0].length; j++) for (int i = 0; i < arg.length; i++) res[k++] = arg[i][j]; return res; } /** * Computes the discrete convolution function for the vectors x * and z from start to end. * The function is defined as *

* (x*z)[m] = sum_n ( x[n]z[m-n] ); m, n start with 0. * * * @param x * Nx1 vector * @param z * Lx1 vector * @param start * the first convolution to compute, zero based * @param end * the last convolution to compute, zero based, max number is * x.length + z.length - 2;
* if end < 0, then max number is used * * @return Qx1 result, where Q = (end - start+ 1), if * end < 0, the start 'th to the last * convolutions are computed * * @throws IllegalArgumentException *

*/ public static double[] conv(double[] x, double[] z, int start, int end) { if (x == null || z == null) throw new IllegalArgumentException("Array argument was null."); if (x.length == 0 || z.length == 0) throw new IllegalArgumentException( "Array argument contained zero elements."); if (start < 0) throw new IllegalArgumentException("Start index was < 0."); if (start > end && end >= 0) throw new IllegalArgumentException( "Wrong index order: start > end."); if (end > x.length + z.length - 2) throw new IllegalArgumentException("End index [" + end + "] exceeds maximum [" + (x.length + z.length - 2) + "]."); // set end to max if < 0 end = (end < 0) ? x.length + z.length - 2 : end; double[] conv = new double[end - start + 1]; for (int i = start; i <= end; i++) for (int j = 0; j <= i; j++) { // zeros if arrays contain no elements at some position double xx = (j < x.length) ? xx = x[j] : 0; double zz = (i - j < z.length) ? z[i - j] : 0; conv[i - start] += xx * zz; } return conv; } /** * Implementation of the fractional difference operator, see
* J. R. M. Hosking "Fractional Differencing", Biometrika (1981), 68 (1), * pp. 165-76 . equation 2.1. * * * @param y * Tx1 time series to be differences * @param d * order of differencing * @return Tx1 vector with differences series * @throws IllegalArgumentException * if (y == null) or if d equals * Double.NaN */ public static double[] fracdiff(double[] y, double d) { if (y == null) throw new IllegalArgumentException("Array argument was null."); if (Double.isNaN(d)) throw new IllegalArgumentException("Differencing argument was NaN."); int T = y.length; if (T == 0) return new double[0]; double[] res = new double[T + 1]; res[0] = 1; double[] trend = UMatrix.seqa(1, 1, T - 1); double[] mat1 = new double[trend.length]; for (int i = 0; i < mat1.length; i++) mat1[i] = (trend[i] - 1 - d) / trend[i]; res[1] = mat1[0]; for (int i = 1; i < T - 1; i++) res[i + 1] = res[i] * mat1[i]; double[] fDiff = conv(y, res, 0, T - 1); return fDiff; } }

Ads help maintain this website.