diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java | 284 |
1 files changed, 163 insertions, 121 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java index 6b8cdc31..fc514a65 100644 --- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java +++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -75,16 +75,17 @@ public final class VMath { */ public static final double[] randomNormalizedVector(final int dimensionality) { final double[] v = new double[dimensionality]; - for (int i = 0; i < dimensionality; i++) { + for(int i = 0; i < dimensionality; i++) { v[i] = Math.random(); } double norm = euclideanLength(v); - if (norm != 0) { - for (int row = 0; row < v.length; row++) { + if(norm != 0) { + for(int row = 0; row < v.length; row++) { v[row] /= norm; } return v; - } else { + } + else { return randomNormalizedVector(dimensionality); } } @@ -120,7 +121,7 @@ public final class VMath { */ public static final double[][] transpose(final double[] v) { double[][] re = new double[v.length][1]; - for (int i = 0; i < v.length; i++) { + for(int i = 0; i < v.length; i++) { re[i][0] = v[i]; } return re; @@ -136,7 +137,7 @@ public final class VMath { public static final double[] plus(final double[] v1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; final double[] result = new double[v1.length]; - for (int i = 0; i < result.length; i++) { + for(int i = 0; i < result.length; i++) { result[i] = v1[i] + v2[i]; } return result; @@ -153,7 +154,7 @@ public final class VMath { public static final double[] plusTimes(final double[] v1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; final double[] result = new double[v1.length]; - for (int i = 0; i < result.length; i++) { + for(int i = 0; i < result.length; i++) { result[i] = v1[i] + v2[i] * s2; } return result; @@ -170,7 +171,7 @@ public final class VMath { public static final double[] timesPlus(final double[] v1, final double s1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; final double[] result = new double[v1.length]; - for (int i = 0; i < result.length; i++) { + for(int i = 0; i < result.length; i++) { result[i] = v1[i] * s1 + v2[i]; } return result; @@ -188,7 +189,7 @@ public final class VMath { public static final double[] timesPlusTimes(final double[] v1, final double s1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; final double[] result = new double[v1.length]; - for (int i = 0; i < result.length; i++) { + for(int i = 0; i < result.length; i++) { result[i] = v1[i] * s1 + v2[i] * s2; } return result; @@ -203,7 +204,7 @@ public final class VMath { */ public static final double[] plusEquals(final double[] v1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] += v2[i]; } return v1; @@ -219,7 +220,7 @@ public final class VMath { */ public static final double[] plusTimesEquals(final double[] v1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] += s2 * v2[i]; } return v1; @@ -235,7 +236,7 @@ public final class VMath { */ public static final double[] timesPlusEquals(final double[] v1, final double s1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] = v1[i] * s1 + v2[i]; } return v1; @@ -252,7 +253,7 @@ public final class VMath { */ public static final double[] timesPlusTimesEquals(final double[] v1, final double s1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] = v1[i] * s1 + v2[i] * s2; } return v1; @@ -267,7 +268,7 @@ public final class VMath { */ public static final double[] plus(final double[] v1, final double d) { final double[] result = new double[v1.length]; - for (int i = 0; i < result.length; i++) { + for(int i = 0; i < result.length; i++) { result[i] = v1[i] + d; } return result; @@ -281,7 +282,7 @@ public final class VMath { * @return Modified vector */ public static final double[] plusEquals(final double[] v1, final double d) { - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] += d; } return v1; @@ -296,7 +297,7 @@ public final class VMath { */ public static final double[] minus(final double[] v1, final double[] v2) { final double[] sub = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { sub[i] = v1[i] - v2[i]; } return sub; @@ -312,7 +313,7 @@ public final class VMath { */ public static final double[] minusTimes(final double[] v1, final double[] v2, final double s2) { final double[] sub = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { sub[i] = v1[i] - v2[i] * s2; } return sub; @@ -328,7 +329,7 @@ public final class VMath { */ public static final double[] timesMinus(final double[] v1, final double s1, final double[] v2) { final double[] sub = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { sub[i] = v1[i] * s1 - v2[i]; } return sub; @@ -345,7 +346,7 @@ public final class VMath { */ public static final double[] timesMinusTimes(final double[] v1, final double s1, final double[] v2, final double s2) { final double[] sub = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { sub[i] = v1[i] * s1 - v2[i] * s2; } return sub; @@ -360,7 +361,7 @@ public final class VMath { */ public static final double[] minusEquals(final double[] v1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] -= v2[i]; } return v1; @@ -376,7 +377,7 @@ public final class VMath { */ public static final double[] minusTimesEquals(final double[] v1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] -= v2[i] * s2; } return v1; @@ -392,7 +393,7 @@ public final class VMath { */ public static final double[] timesMinusEquals(final double[] v1, final double s1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] = v1[i] * s1 - v2[i]; } return v1; @@ -409,7 +410,7 @@ public final class VMath { */ public static final double[] timesMinusTimesEquals(final double[] v1, final double s1, final double[] v2, final double s2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] = v1[i] * s1 - v2[i] * s2; } return v1; @@ -424,7 +425,7 @@ public final class VMath { */ public static final double[] minus(final double[] v1, final double d) { final double[] result = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { result[i] = v1[i] - d; } return result; @@ -438,7 +439,7 @@ public final class VMath { * @return v1 = v1 - d */ public static final double[] minusEquals(final double[] v1, final double d) { - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] -= d; } return v1; @@ -453,7 +454,7 @@ public final class VMath { */ public static final double[] times(final double[] v1, final double s1) { final double[] v = new double[v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v[i] = v1[i] * s1; } return v; @@ -467,7 +468,7 @@ public final class VMath { * @return v1 = v1 * s1 */ public static final double[] timesEquals(final double[] v1, final double s) { - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { v1[i] *= s; } return v1; @@ -484,8 +485,8 @@ public final class VMath { assert (m2.length == 1) : ERR_MATRIX_INNERDIM; final int columndimension = m2[0].length; final double[][] re = new double[v1.length][columndimension]; - for (int j = 0; j < columndimension; j++) { - for (int i = 0; i < v1.length; i++) { + for(int j = 0; j < columndimension; j++) { + for(int i = 0; i < v1.length; i++) { re[i][j] = v1[i] * m2[0][j]; } } @@ -503,9 +504,9 @@ public final class VMath { assert (m2.length == v1.length) : ERR_MATRIX_INNERDIM; final int columndimension = m2[0].length; final double[][] re = new double[1][columndimension]; - for (int j = 0; j < columndimension; j++) { + for(int j = 0; j < columndimension; j++) { double s = 0; - for (int k = 0; k < v1.length; k++) { + for(int k = 0; k < v1.length; k++) { s += v1[k] * m2[k][j]; } re[0][j] = s; @@ -523,7 +524,7 @@ public final class VMath { public static final double transposeTimes(final double[] v1, final double[] v2) { assert (v2.length == v1.length) : ERR_MATRIX_INNERDIM; double s = 0; - for (int k = 0; k < v1.length; k++) { + for(int k = 0; k < v1.length; k++) { s += v1[k] * v2[k]; } return s; @@ -540,8 +541,8 @@ public final class VMath { assert (m2[0].length == 1) : ERR_MATRIX_INNERDIM; final double[][] re = new double[v1.length][m2.length]; - for (int j = 0; j < m2.length; j++) { - for (int i = 0; i < v1.length; i++) { + for(int j = 0; j < m2.length; j++) { + for(int i = 0; i < v1.length; i++) { re[i][j] = v1[i] * m2[j][0]; } } @@ -557,8 +558,8 @@ public final class VMath { */ public static final double[][] timesTranspose(final double[] v1, final double[] v2) { final double[][] re = new double[v1.length][v2.length]; - for (int j = 0; j < v2.length; j++) { - for (int i = 0; i < v1.length; i++) { + for(int j = 0; j < v2.length; j++) { + for(int i = 0; i < v1.length; i++) { re[i][j] = v1[i] * v2[j]; } } @@ -566,7 +567,8 @@ public final class VMath { } /** - * Returns the scalar product (dot product) of this vector and the specified vector v. + * Returns the scalar product (dot product) of this vector and the specified + * vector v. * * This is the same as transposeTimes. * @@ -577,21 +579,36 @@ public final class VMath { public static final double scalarProduct(final double[] v1, final double[] v2) { assert (v1.length == v2.length) : ERR_VEC_DIMENSIONS; double scalarProduct = 0.0; - for (int row = 0; row < v1.length; row++) { + for(int row = 0; row < v1.length; row++) { scalarProduct += v1[row] * v2[row]; } return scalarProduct; } /** + * Squared Euclidean length of the vector + * + * @param v1 vector + * @return squared Euclidean length of this vector + */ + public static final double squareSum(final double[] v1) { + double acc = 0.0; + for(int row = 0; row < v1.length; row++) { + final double v = v1[row]; + acc += v * v; + } + return acc; + } + + /** * Euclidean length of the vector * * @param v1 vector - * @return euclidean length of this vector + * @return Euclidean length of this vector */ public static final double euclideanLength(final double[] v1) { double acc = 0.0; - for (int row = 0; row < v1.length; row++) { + for(int row = 0; row < v1.length; row++) { final double v = v1[row]; acc += v * v; } @@ -607,8 +624,8 @@ public final class VMath { public static final double[] normalize(final double[] v1) { double norm = euclideanLength(v1); double[] re = new double[v1.length]; - if (norm != 0) { - for (int row = 0; row < v1.length; row++) { + if(norm != 0) { + for(int row = 0; row < v1.length; row++) { re[row] = v1[row] / norm; } } @@ -623,8 +640,8 @@ public final class VMath { */ public static final double[] normalizeEquals(final double[] v1) { double norm = euclideanLength(v1); - if (norm != 0) { - for (int row = 0; row < v1.length; row++) { + if(norm != 0) { + for(int row = 0; row < v1.length; row++) { v1[row] /= norm; } } @@ -643,7 +660,7 @@ public final class VMath { final int columndimension = m2[0].length; double[] sum = new double[v1.length]; - for (int i = 0; i < columndimension; i++) { + for(int i = 0; i < columndimension; i++) { // TODO: optimize - copy less. double[] v_i = getCol(m2, i); plusTimesEquals(sum, v_i, scalarProduct(v1, v_i)); @@ -705,7 +722,7 @@ public final class VMath { */ public static final double[][] unitMatrix(final int dim) { final double[][] e = new double[dim][dim]; - for (int i = 0; i < dim; i++) { + for(int i = 0; i < dim; i++) { e[i][i] = 1; } return e; @@ -731,8 +748,8 @@ public final class VMath { */ public static final double[][] random(final int m, final int n) { final double[][] A = new double[m][n]; - for (int i = 0; i < m; i++) { - for (int j = 0; j < n; j++) { + for(int i = 0; i < m; i++) { + for(int j = 0; j < n; j++) { A[i][j] = Math.random(); } } @@ -748,7 +765,7 @@ public final class VMath { */ public static final double[][] identity(final int m, final int n) { final double[][] A = new double[m][n]; - for (int i = 0; i < Math.min(m, n); i++) { + for(int i = 0; i < Math.min(m, n); i++) { A[i][i] = 1.0; } return A; @@ -763,7 +780,7 @@ public final class VMath { */ public static final double[][] diagonal(final double[] v1) { final double[][] result = new double[v1.length][v1.length]; - for (int i = 0; i < v1.length; i++) { + for(int i = 0; i < v1.length; i++) { result[i][i] = v1[i]; } return result; @@ -778,7 +795,7 @@ public final class VMath { public static final double[][] copy(final double[][] m1) { final int columndimension = m1[0].length; final double[][] X = new double[m1.length][columndimension]; - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { System.arraycopy(m1[i], 0, X[i], 0, columndimension); } return X; @@ -793,7 +810,7 @@ public final class VMath { public static final double[] rowPackedCopy(final double[][] m1) { final int columndimension = m1[0].length; double[] vals = new double[m1.length * columndimension]; - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { System.arraycopy(m1[i], 0, vals, i * columndimension, columndimension); } return vals; @@ -808,8 +825,8 @@ public final class VMath { public static final double[] columnPackedCopy(final double[][] m1) { final int columndimension = m1[0].length; final double[] vals = new double[m1.length * columndimension]; - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { vals[i + j * m1.length] = m1[i][j]; } } @@ -828,7 +845,7 @@ public final class VMath { */ public static final double[][] getMatrix(final double[][] m1, final int r0, final int r1, final int c0, final int c1) { final double[][] X = new double[r1 - r0 + 1][c1 - c0 + 1]; - for (int i = r0; i <= r1; i++) { + for(int i = r0; i <= r1; i++) { System.arraycopy(m1[i], c0, X[i - r0], 0, c1 - c0 + 1); } return X; @@ -844,8 +861,8 @@ public final class VMath { */ public static final double[][] getMatrix(final double[][] m1, final int[] r, final int[] c) { final double[][] X = new double[r.length][c.length]; - for (int i = 0; i < r.length; i++) { - for (int j = 0; j < c.length; j++) { + for(int i = 0; i < r.length; i++) { + for(int j = 0; j < c.length; j++) { X[i][j] = m1[r[i]][c[j]]; } } @@ -863,7 +880,7 @@ public final class VMath { */ public static final double[][] getMatrix(final double[][] m1, final int[] r, final int c0, final int c1) { final double[][] X = new double[r.length][c1 - c0 + 1]; - for (int i = 0; i < r.length; i++) { + for(int i = 0; i < r.length; i++) { System.arraycopy(m1[r[i]], c0, X[i], 0, c1 - c0 + 1); } return X; @@ -880,8 +897,8 @@ public final class VMath { */ public static final double[][] getMatrix(final double[][] m1, final int r0, final int r1, final int[] c) { final double[][] X = new double[r1 - r0 + 1][c.length]; - for (int i = r0; i <= r1; i++) { - for (int j = 0; j < c.length; j++) { + for(int i = r0; i <= r1; i++) { + for(int j = 0; j < c.length; j++) { X[i - r0][j] = m1[i][c[j]]; } } @@ -899,7 +916,7 @@ public final class VMath { * @param m2 New values for m1(r0:r1,c0:c1) */ public static final void setMatrix(final double[][] m1, final int r0, final int r1, final int c0, final int c1, final double[][] m2) { - for (int i = r0; i <= r1; i++) { + for(int i = r0; i <= r1; i++) { System.arraycopy(m2[i - r0], 0, m1[i], c0, c1 - c0 + 1); } } @@ -913,8 +930,8 @@ public final class VMath { * @param m2 New values for m1(r(:),c(:)) */ public static final void setMatrix(final double[][] m1, final int[] r, final int[] c, final double[][] m2) { - for (int i = 0; i < r.length; i++) { - for (int j = 0; j < c.length; j++) { + for(int i = 0; i < r.length; i++) { + for(int j = 0; j < c.length; j++) { m1[r[i]][c[j]] = m2[i][j]; } } @@ -930,7 +947,7 @@ public final class VMath { * @param m2 New values for m1(r(:),c0:c1) */ public static final void setMatrix(final double[][] m1, final int[] r, final int c0, final int c1, final double[][] m2) { - for (int i = 0; i < r.length; i++) { + for(int i = 0; i < r.length; i++) { System.arraycopy(m2[i], 0, m1[r[i]], c0, c1 - c0 + 1); } } @@ -945,8 +962,8 @@ public final class VMath { * @param m2 New values for m1(r0:r1,c(:)) */ public static final void setMatrix(final double[][] m1, final int r0, final int r1, final int[] c, final double[][] m2) { - for (int i = r0; i <= r1; i++) { - for (int j = 0; j < c.length; j++) { + for(int i = r0; i <= r1; i++) { + for(int j = 0; j < c.length; j++) { m1[i][c[j]] = m2[i - r0][j]; } } @@ -985,7 +1002,7 @@ public final class VMath { */ public static final double[] getCol(double[][] m1, int col) { double[] ret = new double[m1.length]; - for (int i = 0; i < ret.length; i++) { + for(int i = 0; i < ret.length; i++) { ret[i] = m1[i][col]; } return ret; @@ -1000,7 +1017,7 @@ public final class VMath { */ public static final void setCol(final double[][] m1, final int c, final double[] column) { assert (column.length == m1.length) : ERR_DIMENSIONS; - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { m1[i][c] = column[i]; } } @@ -1014,8 +1031,8 @@ public final class VMath { public static final double[][] transpose(final double[][] m1) { final int columndimension = getColumnDimensionality(m1); final double[][] re = new double[columndimension][m1.length]; - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { re[j][i] = m1[i][j]; } } @@ -1055,8 +1072,8 @@ public final class VMath { public static final double[][] plusEquals(final double[][] m1, final double[][] m2) { final int columndimension = getColumnDimensionality(m1); assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : ERR_MATRIX_DIMENSIONS; - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { m1[i][j] += m2[i][j]; } } @@ -1074,8 +1091,8 @@ public final class VMath { public static final double[][] plusTimesEquals(final double[][] m1, final double[][] m2, final double s2) { final int columndimension = getColumnDimensionality(m1); assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : ERR_MATRIX_DIMENSIONS; - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { m1[i][j] += s2 * m2[i][j]; } } @@ -1115,8 +1132,8 @@ public final class VMath { public static final double[][] minusEquals(final double[][] m1, final double[][] m2) { final int columndimension = getColumnDimensionality(m1); assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : ERR_MATRIX_DIMENSIONS; - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { m1[i][j] -= m2[i][j]; } } @@ -1133,10 +1150,10 @@ public final class VMath { */ public static final double[][] minusTimesEquals(final double[][] m1, final double[][] m2, final double s2) { assert (getRowDimensionality(m1) == getRowDimensionality(m2) && getColumnDimensionality(m1) == getColumnDimensionality(m2)) : ERR_MATRIX_DIMENSIONS; - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { final double[] row1 = m1[i]; final double[] row2 = m2[i]; - for (int j = 0; j < row1.length; j++) { + for(int j = 0; j < row1.length; j++) { row1[j] -= s2 * row2[j]; } } @@ -1162,9 +1179,9 @@ public final class VMath { * @return m1 = s1 * m1, overwriting m1 */ public static final double[][] timesEquals(final double[][] m1, final double s1) { - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { final double[] row = m1[i]; - for (int j = 0; j < row.length; j++) { + for(int j = 0; j < row.length; j++) { row[j] *= s1; } } @@ -1186,17 +1203,17 @@ public final class VMath { final double[][] r2 = new double[m1.length][bcolumndimension]; // Optimized ala Jama. jik order. final double[] Bcolj = new double[columndimension]; - for (int j = 0; j < bcolumndimension; j++) { + for(int j = 0; j < bcolumndimension; j++) { // Make a linear copy of column j from B // TODO: use column getter from B? - for (int k = 0; k < columndimension; k++) { + for(int k = 0; k < columndimension; k++) { Bcolj[k] = m2[k][j]; } // multiply it with each row from A - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { final double[] Arowi = m1[i]; double s = 0; - for (int k = 0; k < columndimension; k++) { + for(int k = 0; k < columndimension; k++) { s += Arowi[k] * Bcolj[k]; } r2[i][j] = s; @@ -1216,10 +1233,10 @@ public final class VMath { assert (v2.length == getColumnDimensionality(m1)) : ERR_MATRIX_INNERDIM; final double[] re = new double[m1.length]; // multiply it with each row from A - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { final double[] Arowi = m1[i]; double s = 0; - for (int k = 0; k < Arowi.length; k++) { + for(int k = 0; k < Arowi.length; k++) { s += Arowi[k] * v2[k]; } re[i] = s; @@ -1239,9 +1256,9 @@ public final class VMath { assert (v2.length == m1.length) : ERR_MATRIX_INNERDIM; final double[] re = new double[columndimension]; // multiply it with each row from A - for (int i = 0; i < columndimension; i++) { + for(int i = 0; i < columndimension; i++) { double s = 0; - for (int k = 0; k < m1.length; k++) { + for(int k = 0; k < m1.length; k++) { s += m1[k][i] * v2[k]; } re[i] = s; @@ -1262,15 +1279,15 @@ public final class VMath { assert (m2.length == m1.length) : ERR_MATRIX_INNERDIM; final double[][] re = new double[coldim1][coldim2]; final double[] Bcolj = new double[m1.length]; - for (int j = 0; j < coldim2; j++) { + for(int j = 0; j < coldim2; j++) { // Make a linear copy of column j from B - for (int k = 0; k < m1.length; k++) { + for(int k = 0; k < m1.length; k++) { Bcolj[k] = m2[k][j]; } // multiply it with each row from A - for (int i = 0; i < coldim1; i++) { + for(int i = 0; i < coldim1; i++) { double s = 0; - for (int k = 0; k < m1.length; k++) { + for(int k = 0; k < m1.length; k++) { s += m1[k][i] * Bcolj[k]; } re[i][j] = s; @@ -1282,6 +1299,7 @@ public final class VMath { /** * Linear algebraic matrix multiplication, a<sup>T</sup> * B * c * + * @param a vector on the left * @param B matrix * @param c vector on the right * @return Matrix product, a<sup>T</sup> * B * c @@ -1289,10 +1307,10 @@ public final class VMath { public static double transposeTimesTimes(final double[] a, final double[][] B, final double[] c) { assert (B.length == a.length) : ERR_MATRIX_INNERDIM; double sum = 0.0; - for (int j = 0; j < B[0].length; j++) { + for(int j = 0; j < B[0].length; j++) { // multiply it with each row from A double s = 0; - for (int k = 0; k < a.length; k++) { + for(int k = 0; k < a.length; k++) { s += a[k] * B[k][j]; } sum += s * c[j]; @@ -1310,13 +1328,13 @@ public final class VMath { public static final double[][] timesTranspose(final double[][] m1, final double[][] m2) { assert (getColumnDimensionality(m2) == getColumnDimensionality(m1)) : ERR_MATRIX_INNERDIM; final double[][] re = new double[m1.length][m2.length]; - for (int j = 0; j < re.length; j++) { + for(int j = 0; j < re.length; j++) { final double[] Browj = m2[j]; // multiply it with each row from A - for (int i = 0; i < m1.length; i++) { + for(int i = 0; i < m1.length; i++) { final double[] Arowi = m1[i]; double s = 0; - for (int k = 0; k < Browj.length; k++) { + for(int k = 0; k < Browj.length; k++) { s += Arowi[k] * Browj[k]; } re[i][j] = s; @@ -1338,17 +1356,17 @@ public final class VMath { final double[][] re = new double[getColumnDimensionality(m1)][m2.length]; // Optimized ala Jama. jik order. final double[] Acolj = new double[m1.length]; - for (int j = 0; j < re.length; j++) { + for(int j = 0; j < re.length; j++) { // Make a linear copy of column j from B - for (int k = 0; k < m1.length; k++) { + for(int k = 0; k < m1.length; k++) { Acolj[k] = m1[k][j]; } final double[] Xrow = re[j]; // multiply it with each row from A - for (int i = 0; i < m2.length; i++) { + for(int i = 0; i < m2.length; i++) { final double[] Browi = m2[i]; double s = 0; - for (int k = 0; k < m1.length; k++) { + for(int k = 0; k < m1.length; k++) { s += Browi[k] * Acolj[k]; } Xrow[i] = s; @@ -1358,6 +1376,28 @@ public final class VMath { } /** + * Linear algebraic matrix multiplication, (a-c)<sup>T</sup> * B * (a-c) + * + * @param B matrix + * @param a First vector + * @param c Center vector + * @return Matrix product, (a-c)<sup>T</sup> * B * (a-c) + */ + public static double mahalanobisDistance(final double[][] B, final double[] a, final double[] c) { + assert (B.length == a.length && a.length == c.length) : ERR_MATRIX_INNERDIM; + double sum = 0.0; + for(int j = 0; j < B[0].length; j++) { + // multiply it with each row from A + double s = 0; + for(int k = 0; k < a.length; k++) { + s += (a[k] - c[k]) * B[k][j]; + } + sum += s * (a[j] - c[j]); + } + return sum; + } + + /** * getDiagonal returns array of diagonal-elements. * * @param m1 Input matrix @@ -1366,7 +1406,7 @@ public final class VMath { public static final double[] getDiagonal(final double[][] m1) { final int dim = Math.min(getColumnDimensionality(m1), m1.length); final double[] diagonal = new double[dim]; - for (int i = 0; i < dim; i++) { + for(int i = 0; i < dim; i++) { diagonal[i] = m1[i][i]; } return diagonal; @@ -1379,17 +1419,18 @@ public final class VMath { */ public static final void normalizeColumns(final double[][] m1) { final int columndimension = getColumnDimensionality(m1); - for (int col = 0; col < columndimension; col++) { + for(int col = 0; col < columndimension; col++) { double norm = 0.0; - for (int row = 0; row < m1.length; row++) { + for(int row = 0; row < m1.length; row++) { norm = norm + (m1[row][col] * m1[row][col]); } norm = Math.sqrt(norm); - if (norm != 0) { - for (int row = 0; row < m1.length; row++) { + if(norm != 0) { + for(int row = 0; row < m1.length; row++) { m1[row][col] /= norm; } - } else { + } + else { // TODO: else: throw an exception? } } @@ -1409,11 +1450,12 @@ public final class VMath { final int rcolumndimension = columndimension + ccolumndimension; final double[][] result = new double[m1.length][rcolumndimension]; - for (int i = 0; i < rcolumndimension; i++) { + for(int i = 0; i < rcolumndimension; i++) { // FIXME: optimize - excess copying! - if (i < columndimension) { + if(i < columndimension) { setCol(result, i, getCol(m1, i)); - } else { + } + else { setCol(result, i, getCol(m2, i - columndimension)); } } @@ -1431,10 +1473,10 @@ public final class VMath { double[][] v = copy(m1); // FIXME: optimize - excess copying! - for (int i = 1; i < columndimension; i++) { + for(int i = 1; i < columndimension; i++) { final double[] u_i = getCol(m1, i); final double[] sum = new double[m1.length]; - for (int j = 0; j < i; j++) { + for(int j = 0; j < i; j++) { final double[] v_j = getCol(v, j); double scalar = scalarProduct(u_i, v_j) / scalarProduct(v_j, v_j); plusEquals(sum, times(v_j, scalar)); @@ -1478,25 +1520,25 @@ public final class VMath { * @return true if delta smaller than maximum */ public static final boolean almostEquals(final double[][] m1, final double[][] m2, final double maxdelta) { - if (m1 == m2) { + if(m1 == m2) { return true; } - if (m2 == null) { + if(m2 == null) { return false; } - if (m1.getClass() != m2.getClass()) { + if(m1.getClass() != m2.getClass()) { return false; } - if (m1.length != m2.length) { + if(m1.length != m2.length) { return false; } final int columndimension = getColumnDimensionality(m1); - if (columndimension != getColumnDimensionality(m2)) { + if(columndimension != getColumnDimensionality(m2)) { return false; } - for (int i = 0; i < m1.length; i++) { - for (int j = 0; j < columndimension; j++) { - if (Math.abs(m1[i][j] - m2[i][j]) > maxdelta) { + for(int i = 0; i < m1.length; i++) { + for(int j = 0; j < columndimension; j++) { + if(Math.abs(m1[i][j] - m2[i][j]) > maxdelta) { return false; } } |