view src/samer/maths/Matrix.java @ 0:bf79fb79ee13

Initial Mercurial check in.
author samer
date Tue, 17 Jan 2012 17:50:20 +0000
parents
children
line wrap: on
line source
/*
 *	Matrix.java	
 *
 *	Copyright (c) 2000, Samer Abdallah, King's College London.
 *	All rights reserved.
 *
 *	This software is provided AS iS and WITHOUT ANY WARRANTY; 
 *	without even the implied warranty of MERCHANTABILITY or 
 *	FITNESS FOR A PARTICULAR PURPOSE.
 */

package	samer.maths;
import	samer.core.*;
import   samer.core.util.*;
import	java.util.*;
import	java.io.*;

/**
	Represents a bundling of a Jama.Matrix with Viewable bits.
	Create one of these and you can either keep it invisible,
	expose its UI yourself, or let the Viewable framework
	expose a default viewer automatically
 */

public class Matrix extends Jama.Matrix implements Mat, Saveable
{
	Viewable	viewable;

	// ............... Viewable bits .................

	private class Vbl extends Viewable {
		Vbl(String nm) { super(nm); }
		Vbl() { super("matrix"); }

		/** returns current Agent if there is one, creates a MatrixAgent if not */
		public Agent getAgent() {
			if (super.getAgent()==null) setAgent(new MatrixAgent(Matrix.this));
			return super.getAgent();
		}

		public Matrix getMatrix() { return Matrix.this; }
		public Viewer getViewer()
		{
			BaseViewer		vwr = new BaseViewer(this);
			StringBuffer	buf = new StringBuffer();

			buf.append(getLabel())
				.append(" (").append(getRowDimension())
				.append(" by ").append(getColumnDimension())
				.append(")");
			vwr.setText(buf.toString());

			return vwr;
		}
	}

	public Observable	observable() { return viewable; }
	public Viewable	viewable() { return viewable; }
	public boolean		equals(Observable o) { return viewable==o; }
	public Node		getNode() { return viewable.getNode(); }

	public final void	changed(Object o)	{ viewable.changed(o); }
	public final void	changed() { viewable.changed(); }
	public void	addObserver(Observer o) { viewable.addObserver(o); }
	public void	deleteObserver(Observer o) { viewable.deleteObserver(o); }
	public void dispose() { viewable.dispose(); }

	public void copyFrom(double[][] src) {
		double[][] dest=getArray();
		for (int i=0; i<src.length; i++) {
			Mathx.copy(src[i],dest[i]);
			changed();
		}
	}

	// ................................................

	public Matrix( String name, int m, int n) { this(name,m,n,1); }
	public Matrix( String name, int m, int n, int flags) {
		super(m,n); viewable=new Vbl(name);
		if (flags==1) Shell.registerViewable(viewable);
	}


	public Matrix( int m, int n) { super(m,n); viewable=new Vbl(); Shell.registerViewable(viewable); }
	public Matrix( double array[][]) { super(array); viewable=new Vbl(); Shell.registerViewable(viewable); }

	public String toString() {
		StringBuffer	buf = new StringBuffer();

		buf.append(viewable.getLabel())
			.append(" (").append(getRowDimension())
			.append(" by ").append(getColumnDimension())
			.append(")");
		return buf.toString();
	}

	// implement Mat interface
	public int width() { return getColumnDimension(); }
	public int height() { return getRowDimension(); }

	public Agent getAgent() { return viewable.getAgent(); }


	// ................................................
	// some useful additions to Matrix functionality

	public void set( Generator g) {
		for (int i=0; i<m; i++) g.next(A[i]);
	}

	public void apply( Function f) {
		for (int i=0; i<m; i++) f.apply(A[i]);
	}

	public void add( Generator g)
	{
		for (int i=0; i<m; i++) {
			for (int j=0; j<n; j++) {
				A[i][j]+=g.next();
			}
		}
	}


   /** Set to identity matrix */

   public void identity()
   {
      for (int i = 0; i < m; i++) {
         for (int j = 0; j < n; j++) {
            A[i][j] = (i == j ? 1.0 : 0.0);
         }
      }
   }

	public static Jama.Matrix identity(Jama.Matrix a)
	{
		double [][] A=a.getArray();
		int m=a.getRowDimension();
		int n=a.getColumnDimension();
		for (int i = 0; i < m; i++) {
			for (int j = 0; j < n; j++) {
				A[i][j] = (i == j ? 1.0 : 0.0);
			}
		}
		return a;
	}
	
   /** Set to zero matrix */

   public void zero() {
      for (int i = 0; i < m; i++) { Mathx.zero(A[i]); }
   }

   /** Set to given matrix
     * (need to make sure both matrices are the same size)
		@param b the matrix to be copied
     */

   public void assign( Jama.Matrix b)
   {
      double[][] B=b.getArray();
	  int mmax = B.length>m ? m : B.length;
	  int nmax = B[0].length>n ? n : B[0].length;

      for (int i = 0; i < mmax; i++) {
		System.arraycopy(B[i],0,A[i],0,nmax);
      }
   }

	// Saveable implementation

	public void load(InputStream in) throws Exception {
		ObjectInputStream	o=new ObjectInputStream(in);
		assign((Jama.Matrix)o.readObject());
		changed();
	}

	public void save(OutputStream out) throws Exception {
		ObjectOutputStream	o=new ObjectOutputStream(out);
		o.writeObject(new Jama.Matrix(getArray()));
	}

	public void write(Writer wr) throws Exception {
		print(new PrintWriter(wr,true), new DoubleFormat(16),4);
	}

	public void read(Reader rdr) throws Exception {
		Jama.Matrix A=Jama.Matrix.read(new BufferedReader(rdr));
		assign(A);	changed();
	}

/** Symmetrise in place preserving trace.
		Will fail if matrix is not square. */
	public void symmetrise()
	{
		double a, _G[][]=getArray();
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<n; j++) {
				a=(_G[i][j]+_G[j][i])/2;
				_G[i][j]=_G[j][i]=a;
			}
		}
	}

	/** Antisymmetrise in place.
		Will fail if matrix is not square. */
	public void antisymmetrise()
	{
		double a, _G[][]=getArray();
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<n; j++) {
				a=(_G[i][j]-_G[j][i])/2;
				_G[i][j]=a;	_G[j][i]=-a;
			}
			_G[i][i]=0;
		}
	}

	/** return log(abs(det(this))) (must be square matrix) */
	
	public double logdet() {
		int n=getRowDimension();
		double [][] x=lu().getU().getArray();
		double L=0;
		for (int i=0; i<n; i++) L+= Math.log(Math.abs(x[i][i]));
		return L;
	}
	// ................................................

	public Vec getRow(int k) { return new Row(k); }
	public Vec getColumn(int k) { return new Column(k); }

	public static Vec getDiagonal(final Jama.Matrix A) {
		return new Vec() {
			double[][] x=A.getArray();

			public int size() { return x.length; }
			public double[] array() { return null; }
			public Mat mat() {
				return new Mat() {
					// Mat implementation
					public int width() { return x.length; }
					public int height() { return 1; }
					public double get( int i, int j) { return x[j][j]; }
					public void set( int i, int j, double t) { x[j][j]=t; }
				};
			}
			public Iterator iterator() {
				return new Iterator() {
					int i=0, n=x.length;
					public void rewind() { i=0; }
					public boolean more() { return i<n; }
					public double next() {
						double y=x[i][i]; i++; return y;
					}
				};
			}
		};
	}

	private abstract class Slice implements Vec, Vec.Iterator
	{
		protected int i, j, n;

		Slice(int n, int j) { this.n=n; this.j=j; i=0; }

		// Vec implementation
		public final Vec.Iterator	iterator() { i=0; return this; }
		public final int	size() { return n; }
		public final void	rewind() { i=0; }
		public final boolean more() { return i<n; }
	}

	private class Row extends Slice {
		double []	x;

		public Row(int rownum) {
			super(Matrix.this.getColumnDimension(),rownum);
			x=getArray()[rownum];
		}

		public final double		next() { return x[i++]; }
		public final double[]	array() { return x; }
		public final Mat		mat() {
			return new Mat() {
				// Mat implementation
				public int width() { return Row.this.n; }
				public int height() { return 1; }
				public double get( int i, int j) { return x[j]; }
				public void set( int i, int j, double t) { x[j]=t; }
			};
		}
	}

	private class Column extends Slice {
		double [][]	x;
		int			j;

		public Column(int colnum) {
			super(Matrix.this.getRowDimension(),colnum);
			x=getArray();
			j=colnum;
		}

		public final double next() { return x[i++][j]; }
		public final double[] array() { return null; }
		public final Mat		mat() {
			return new Mat() {
				public final int width() { return Column.this.n; }
				public final int height() { return 1; }
				public final double get( int i, int k) { return x[k][j]; }
				public final void set( int i, int k, double t) { x[k][j]=t; }
			};
		}
	}
}