/* GNU General Public License CacheWolf is a software for PocketPC, Win and Linux that enables paperless caching. It supports the sites geocaching.com and opencaching.de Copyright (C) 2006 CacheWolf development team See http://www.cachewolf.de/ for more information. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package CacheWolf.utils; public final class Matrix { int iDF = 0; public double matrix[][] = new double[0][0]; public Matrix(int rows, int cols) { matrix = new double[rows][cols]; } public Matrix(Matrix srcMatrix) { matrix = new double[srcMatrix.matrix.length][srcMatrix.matrix[0].length]; for (int i = 0; i < srcMatrix.matrix.length; i++) for (int j = 0; j < srcMatrix.matrix[i].length; j++) matrix[i][j] = srcMatrix.matrix[i][j]; } /** * Method to multiply this matrix with another matrix. * The result is stored in this matrix! */ public void Multiply(Matrix srcMatrix) { double m[][] = new double[matrix.length][srcMatrix.matrix[0].length]; for (int i = 0; i < m.length; i++) for (int j = 0; j < m[i].length; j++) { m[i][j] = calculateRowColumnProduct(matrix, i, srcMatrix.matrix, j); } matrix = m; } /** * Method to calculate the row column product of two matrices. * Is used by the Multiply method. */ private double calculateRowColumnProduct(double[][] A, int row, double[][] B, int col) { double product = 0; for (int i = 0; i < A[row].length; i++) { product += A[row][i] * B[i][col]; } return product; } public void MultiplyByScalar(double f) { for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[0].length; j++) matrix[i][j] = matrix[i][j] * f; } public void add(Matrix a) { for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[0].length; j++) matrix[i][j] = matrix[i][j] + a.matrix[i][j]; } /** * Method to transpose a matrix * example: | 1 2 | * | 3 4 | * | 5 6 | * would become: |1 3 5 | * |2 4 6 | */ public void Transpose() { double m[][] = new double[matrix[0].length][matrix.length]; for (int i = 0; i < matrix.length; i++) for (int j = 0; j < matrix[i].length; j++) m[j][i] = matrix[i][j]; matrix = new double[m.length][m[0].length]; for (int i = 0; i < m.length; i++) for (int j = 0; j < m[i].length; j++) matrix[i][j] = m[i][j]; } /** * private version of the Transpose method. * used internally in this class */ private double[][] Transpose2(double[][] a) { double m[][] = new double[a[0].length][a.length]; for (int i = 0; i < a.length; i++) for (int j = 0; j < a[i].length; j++) m[j][i] = a[i][j]; return m; } /** * Method used to help calculate determinate */ private double[][] UpperTriangle(double[][] m) { double f1 = 0; double temp = 0; int tms = m.length; // get This Matrix Size (could be smaller than // global) int v = 1; iDF = 1; for (int col = 0; col < tms - 1; col++) { for (int row = col + 1; row < tms; row++) { v = 1; outahere: while (m[col][col] == 0) // check if 0 in diagonal { // if so switch until not if (col + v >= tms) // check if switched all rows { iDF = 0; break outahere; } else { for (int c = 0; c < tms; c++) { temp = m[col][c]; m[col][c] = m[col + v][c]; // switch rows m[col + v][c] = temp; } v++; // count row switchs iDF = iDF * -1; // each switch changes determinant // factor } } if (m[col][col] != 0) { try { f1 = (-1) * m[row][col] / m[col][col]; for (int i = col; i < tms; i++) { m[row][i] = f1 * m[col][i] + m[row][i]; } } catch (Exception e) { } } } } return m; } /** * Method to calculate the determinate of a matrix */ public double Determinant(double[][] pMatrix) { int tms = pMatrix.length; double det = 1; pMatrix = UpperTriangle(pMatrix); for (int i = 0; i < tms; i++) { det = det * pMatrix[i][i]; } // multiply down diagonal det = det * iDF; // adjust w/ determinant factor return det; } /** * Method to calculate the inverse of this matrix. * The result is stored in this matrix! */ public void Inverse() { // Formula used to Calculate Inverse: // inv(A) = 1/det(A) * adj(A) int tms = matrix.length; double m[][] = new double[tms][tms]; double mm[][] = Adjoint(matrix); double det = Determinant(matrix); double dd = 0; if (det == 0) { // todo throw exception // "Determinant Equals 0, Not Invertible.") } else { dd = 1 / det; } for (int i = 0; i < tms; i++) for (int j = 0; j < tms; j++) { m[i][j] = dd * mm[i][j]; } //Store back results matrix = new double[m.length][m[0].length]; for (int i = 0; i < m.length; i++) for (int j = 0; j < m[i].length; j++) matrix[i][j] = m[i][j]; } /** * Method to calculate the adjoint of a matrix. * Required to calculate the inverse of a matrix. */ private double[][] Adjoint(double[][] a) { int tms = a.length; double m[][] = new double[tms][tms]; int ii, jj, ia, ja; double det; for (int i = 0; i < tms; i++) for (int j = 0; j < tms; j++) { ia = ja = 0; double ap[][] = new double[tms - 1][tms - 1]; for (ii = 0; ii < tms; ii++) { for (jj = 0; jj < tms; jj++) { if ((ii != i) && (jj != j)) { ap[ia][ja] = a[ii][jj]; ja++; } } if ((ii != i) && (jj != j)) { ia++; } ja = 0; } det = Determinant(ap); m[i][j] = java.lang.Math.pow(-1, i + j) * det; } m = Transpose2(m); return m; } /** * "Old" helper method used by some other classes in cachewolf. */ // No reason for deprecation, so I removed it. Or is there a better substitution for this // method? // @deprecated Do not use when coding new classes! public static double dot(double p1, double p2, double q1, double q2, double x1, double x2) { double dt, AB0, AB1, BC0, BC1 = 0; AB0 = q1 - p1; AB1 = q2 - p2; BC0 = x1 - q1; BC1 = x2 - q2; dt = AB0 * BC0 + AB1 * BC1; return dt; } /** * "Old" helper method used by some other classes in cachewolf. */ // No reason for deprecation, so I removed it. Or is there a better substitution for this // method? // @deprecated Do not use when coding new classes! public static double cross(double p1, double p2, double q1, double q2, double x1, double x2) { double cr, AB0, AB1, AC0, AC1 = 0; AB0 = q1 - p1; AB1 = q2 - p2; AC0 = x1 - p1; AC1 = x2 - p2; cr = AB0 * AC1 - AB1 * AC0; return cr; } /** * "Old" helper method used by some other classes in cachewolf. */ // No reason for deprecation, so I removed it. Or is there a better substitution for this // method? // @deprecated Do not use when coding new classes! public static double dist(double p1, double p2, double q1, double q2) { double d1, d2, dt = 0; d1 = p1 - q1; d2 = p2 - q2; dt = d1 * d1 + d2 * d2; dt = java.lang.Math.sqrt(dt); return dt; } }