/* IMatrix.java * * Copyright (C) 1997-2007 Stephan Michels <stephan@vern.chem.tu-berlin.de> * * Contact: cdk-devel@lists.sourceforge.net * * 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 2.1 * of the License, or (at your option) any later version. * All we ask is that proper credit is given for our work, which includes * - but is not limited to - adding the above copyright notice to the beginning * of your source code files, and to any copyright notice that you may distribute * with programs based on this work. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * */ package org.openscience.cdk.math; import java.text.DecimalFormat; /** * This class contains a complex matrix. * * @cdk.module qm */ public class IMatrix { // Attention! Variables are unprotected /** the real part of the content */ public double[][] realmatrix; /** the imaginary part of the content */ public double[][] imagmatrix; /** the count of rows of the matrix */ public int rows; /** the count of columns of the matrix */ public int columns; /** * Creates a complex matrix */ public IMatrix(int rows, int columns) { this.rows = rows; this.columns = columns; realmatrix = new double[rows][columns]; imagmatrix = new double[rows][columns]; } /** * Creates a complex copy of a matrix */ public IMatrix(Matrix m) { rows = m.rows; columns = m.columns; int i,j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { realmatrix[i][j] = m.matrix[i][j]; imagmatrix[i][j] = 0d; } } /** * Returns the count of rows */ public int getRows() { return rows; } /** * Returns the count of columns */ public int getColumns() { return columns; } /** * Creates a vector with the content of a row from this matrix */ public IVector getVectorFromRow(int index) { IVector result = new IVector(columns); for(int i=0; i<columns; i++) { result.realvector[i] = realmatrix[index][i]; result.imagvector[i] = imagmatrix[index][i]; } return result; } /** * Creates a vector with the content of a column from this matrix */ public IVector getVectorFromColumn(int index) { IVector result = new IVector(rows); for(int i=0; i<rows; i++) { result.realvector[i] = realmatrix[i][index]; result.imagvector[i] = imagmatrix[i][index]; } return result; } /** * Creates a vector with the content of the diagonal elements from this matrix */ public IVector getVectorFromDiagonal() { int size = Math.min(rows, columns); IVector result = new IVector(size); for(int i=0; i<rows; i++) { result.realvector[i] = realmatrix[i][i]; result.imagvector[i] = imagmatrix[i][i]; } return result; } /** * Addition from two matrices */ public IMatrix add(IMatrix b) { IMatrix result = new IMatrix(rows,columns); add(b, result); return result; } /** * Addition from two matrices */ public void add(IMatrix b, IMatrix result) { if ((b==null) || (rows!=b.rows) || (columns!=b.columns)) return; if ((result.rows!=rows) || (result.columns!=columns)) result.reshape(rows,columns); int i, j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.realmatrix[i][j] = realmatrix[i][j]+b.realmatrix[i][j]; result.imagmatrix[i][j] = imagmatrix[i][j]+b.imagmatrix[i][j]; } } /** * Subtraktion from two matrices */ public IMatrix sub(IMatrix b) { IMatrix result = new IMatrix(rows,columns); sub(b, result); return result; } /** * Subtraktion from two matrices */ public void sub(IMatrix b, IMatrix result) { if ((b==null) || (rows!=b.rows) || (columns!=b.columns)) return; if ((result.rows!=rows) || (result.columns!=columns)) result.reshape(rows,columns); int i, j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.realmatrix[i][j] = realmatrix[i][j]-b.realmatrix[i][j]; result.imagmatrix[i][j] = imagmatrix[i][j]-b.imagmatrix[i][j]; } } /** * Multiplikation from two matrices */ public IMatrix mul(IMatrix b) { IMatrix result = new IMatrix(rows,columns); mul(b, result); return result; } /** * Multiplikation from two matrices */ public void mul(IMatrix b, IMatrix result) { if ((b==null) || (columns!=b.rows)) return; if ((result.rows!=rows) || (result.columns!=b.columns)) result.reshape(rows,b.columns); int i,j,k; double realsum,imagsum; for(i=0; i<rows; i++) for(k=0; k<b.columns; k++) { realsum = 0; imagsum = 0; for(j=0; j<columns; j++) { realsum += realmatrix[i][j]*b.realmatrix[j][k]-imagmatrix[i][j]*b.imagmatrix[j][k]; imagsum += realmatrix[i][j]*b.imagmatrix[j][k]+imagmatrix[i][j]*b.realmatrix[j][k]; } result.realmatrix[i][k] = realsum; result.imagmatrix[i][k] = imagsum; } } /** * Multiplikation from a vector and a matrix */ public IVector mul(IVector a) { IVector result = new IVector(rows); mul(a, result); return result; } /** * Multiplikation from a vector and a matrix */ public void mul(IVector a, IVector result) { if ((a==null) || (columns!=a.size)) return; if (result.size!=rows) result.reshape(rows); int i,j; double realsum, imagsum; for(i=0; i<rows; i++) { realsum = 0; imagsum = 0; for(j=0; j<columns; j++) { realsum += realmatrix[i][j]*a.realvector[j]-imagmatrix[i][j]*a.imagvector[j]; imagsum += realmatrix[i][j]*a.imagvector[j]+imagmatrix[i][j]*a.realvector[j]; } result.realvector[i] = realsum; result.imagvector[i] = imagsum; } } /** * Multiplikation from a scalar and a matrix */ public IMatrix mul(Complex a) { IMatrix result = new IMatrix(rows,columns); mul(a, result); return result; } /** * Multiplikation from a scalar and a matrix */ public void mul(Complex a, IMatrix result) { if ((result.rows!=rows) || (result.columns!=columns)) result.reshape(rows,columns); int i,j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.realmatrix[i][j] = realmatrix[i][j]*a.real-imagmatrix[i][j]*a.imag; result.imagmatrix[i][j] = realmatrix[i][j]*a.imag+imagmatrix[i][j]*a.real; } } /** * Copy a matrix */ public IMatrix duplicate() { IMatrix result = new IMatrix(rows,columns); duplicate(result); return result; } /** * Copy a matrix */ public void duplicate(IMatrix result) { if ((result.rows!=rows) || (result.columns!=columns)) result.reshape(rows,columns); int i,j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.realmatrix[i][j] = realmatrix[i][j]; result.imagmatrix[i][j] = imagmatrix[i][j]; } } /** * Transpose a matrix */ public IMatrix transpose() { IMatrix result = new IMatrix(rows,columns); transpose(result); return result; } /** * Transpose a matrix */ public void transpose(IMatrix result) { if ((result.rows!=rows) || (result.columns!=columns)) result.reshape(rows,columns); int i,j; for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.realmatrix[j][i] = realmatrix[i][j]; result.imagmatrix[j][i] = imagmatrix[i][j]; } } /** * Similar transformation * Ut * M * U */ public IMatrix similar(IMatrix U) { IMatrix result = new IMatrix(rows,columns); similar(U, result); return result; } /** * Similar transformation * Ut * M * U */ public void similar(IMatrix U, IMatrix result) { if ((result.rows!=U.columns) || (result.columns!=U.columns)) result.reshape(U.columns,U.columns); double realsum, imagsum, realinnersum, imaginnersum; for(int i=0; i<U.columns; i++) for(int j=0; j<U.columns; j++) { realsum = 0d; imagsum = 0d; for(int k=0; k<U.columns; k++) { realinnersum = 0d; imaginnersum = 0d; for(int l=0; l<U.columns; l++) { realinnersum += realmatrix[k][l]*U.realmatrix[l][j]-imagmatrix[k][l]*U.imagmatrix[l][j]; imaginnersum += realmatrix[k][l]*U.imagmatrix[l][j]+imagmatrix[k][l]*U.realmatrix[l][j]; } realsum += U.realmatrix[k][i]*realinnersum-U.imagmatrix[k][i]*imaginnersum; imagsum += U.realmatrix[k][i]*imaginnersum+U.imagmatrix[k][i]*realinnersum; } result.realmatrix[i][j] = realsum; result.imagmatrix[i][j] = imagsum; } } /** * Calculates the contraction from a matrix */ public Complex contraction() { int i,j; Complex result = new Complex(0d,0d); for(i=0; i<rows; i++) for(j=0; j<columns; j++) { result.real += realmatrix[i][j]; result.imag += imagmatrix[i][j]; } return result; } /** * Return a matrix as a string */ public String toString() { if ((rows<=0) || (columns<=0)) return "[]"; int i,j; DecimalFormat format = new DecimalFormat("00.0000"); format.setPositivePrefix("+"); StringBuffer str = new StringBuffer(); for(i=0; i<(rows-1); i++) { for(j=0; j<(columns-1); j++) if ((Math.round(realmatrix[i][j]*10000)!=0) && (Math.round(imagmatrix[i][j]*10000)!=0)) str.append(format.format(realmatrix[i][j])+"+i*"+format.format(imagmatrix[i][j])+" "); else str.append("--------+i*-------- "); if ((Math.round(realmatrix[i][columns-1]*10000)!=0) && (Math.round(imagmatrix[i][columns-1]*10000)!=0)) str.append(format.format(realmatrix[i][columns-1])+"+i*"+format.format(imagmatrix[i][columns-1])+"\n"); else str.append("--------+i*--------\n"); } for(j=0; j<(columns-1); j++) if ((Math.round(realmatrix[rows-1][j]*10000)!=0) && (Math.round(imagmatrix[rows-1][j]*10000)!=0)) str.append(format.format(realmatrix[rows-1][j])+"+i*"+format.format(imagmatrix[rows-1][j])+" "); else str.append("--------+i*-------- "); if ((Math.round(realmatrix[rows-1][columns-1]*10000)!=0) && (Math.round(imagmatrix[rows-1][columns-1]*10000)!=0)) str.append(format.format(realmatrix[rows-1][columns-1])+ "+i*"+format.format(imagmatrix[rows-1][columns-1])); else str.append("--------+i*-------- "); return str.toString(); } /** * Resize the matrix */ public void reshape(int newrows, int newcolumns) { if (((newrows==rows) && (newcolumns==columns)) || (newrows<=0) || (newcolumns<=0)) return; double[][] newrealmatrix = new double[newrows][newcolumns]; double[][] newimagmatrix = new double[newrows][newcolumns]; int minrows = Math.min(rows,newrows); int mincolumns = Math.min(columns,newcolumns); int i,j; for(i=0; i<minrows; i++) for(j=0; j<mincolumns; j++) { newrealmatrix[i][j] = realmatrix[i][j]; newimagmatrix[i][j] = imagmatrix[i][j]; } for(i=minrows; i<newrows; i++) for(j=0; j<mincolumns; j++) { newrealmatrix[i][j] = 0d; newimagmatrix[i][j] = 0d; } for(i=0; i<minrows; i++) for(j=mincolumns; j<newcolumns; j++) { newrealmatrix[i][j] = 0d; newimagmatrix[i][j] = 0d; } for(i=minrows; i<newrows; i++) for(j=mincolumns; j<newcolumns; j++) { newrealmatrix[i][j] = 0d; newimagmatrix[i][j] = 0d; } realmatrix = newrealmatrix; imagmatrix = newimagmatrix; rows = newrows; columns = newcolumns; } }