All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jscl.math.numeric.Matrix Maven / Gradle / Ivy

There is a newer version: 1.0.11
Show newest version
package jscl.math.numeric;

import jscl.math.NotDivisibleException;
import jscl.util.ArrayComparator;

import javax.annotation.Nonnull;

public class Matrix extends Numeric {

	@Nonnull
	private final Numeric m[][];

	private final int rows, cols;

	public Matrix(@Nonnull Numeric m[][]) {
		this.m = m;
		rows = m.length;
		cols = m.length > 0 ? m[0].length : 0;
	}

	public Numeric[][] elements() {
		return m;
	}

	public Matrix add(Matrix matrix) {
		Matrix m = newInstance();
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				m.m[i][j] = this.m[i][j].add(matrix.m[i][j]);
			}
		}
		return m;
	}

	@Nonnull
	public Numeric add(@Nonnull Numeric that) {
		if (that instanceof Matrix) {
			return add((Matrix) that);
		} else {
			return add(valueOf(that));
		}
	}

	public Matrix subtract(Matrix matrix) {
		Matrix m = newInstance();
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				m.m[i][j] = this.m[i][j].subtract(matrix.m[i][j]);
			}
		}
		return m;
	}

	@Nonnull
	public Numeric subtract(@Nonnull Numeric that) {
		if (that instanceof Matrix) {
			return subtract((Matrix) that);
		} else {
			return subtract(valueOf(that));
		}
	}

	public Matrix multiply(Matrix matrix) {
		if (cols != matrix.rows) throw new ArithmeticException();
		Matrix m = newInstance(new Numeric[rows][matrix.cols]);
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < matrix.cols; j++) {
				m.m[i][j] = Real.ZERO;
				for (int k = 0; k < cols; k++) {
					m.m[i][j] = m.m[i][j].add(this.m[i][k].multiply(matrix.m[k][j]));
				}
			}
		}
		return m;
	}

	@Nonnull
	public Numeric multiply(@Nonnull Numeric that) {
		if (that instanceof Matrix) {
			return multiply((Matrix) that);
		} else if (that instanceof Vector) {
			Vector v = ((Vector) that).newInstance(new Numeric[rows]);
			Vector v2 = (Vector) that;
			if (cols != v2.n) throw new ArithmeticException();
			for (int i = 0; i < rows; i++) {
				v.element[i] = Real.ZERO;
				for (int k = 0; k < cols; k++) {
					v.element[i] = v.element[i].add(m[i][k].multiply(v2.element[k]));
				}
			}
			return v;
		} else {
			Matrix m = newInstance();
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					m.m[i][j] = this.m[i][j].multiply(that);
				}
			}
			return m;
		}
	}

	@Nonnull
	public Numeric divide(@Nonnull Numeric that) throws NotDivisibleException {

		if (that instanceof Matrix) {
			return multiply(that.inverse());
		} else if (that instanceof Vector) {
			throw new ArithmeticException();
		} else {
			Matrix m = newInstance();
			for (int i = 0; i < rows; i++) {
				for (int j = 0; j < cols; j++) {
					m.m[i][j] = this.m[i][j].divide(that);
				}
			}
			return m;
		}

	}

	@Nonnull
	public Numeric negate() {
		Matrix m = newInstance();
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				m.m[i][j] = this.m[i][j].negate();
			}
		}
		return m;
	}

	public int signum() {
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				int c = m[i][j].signum();
				if (c < 0) {
					return -1;
				} else if (c > 0) {
					return 1;
				}
			}
		}

		return 0;
	}

	@Nonnull
	public Numeric valueOf(@Nonnull Numeric numeric) {
		if (numeric instanceof Matrix || numeric instanceof Vector) {
			throw new ArithmeticException();
		} else {
			Matrix m = (Matrix) identity(rows, cols).multiply(numeric);
			return newInstance(m.m);
		}
	}

	public Numeric[] vectors() {
		Vector v[] = new Vector[rows];
		for (int i = 0; i < rows; i++) {
			v[i] = new Vector(new Numeric[cols]);
			for (int j = 0; j < cols; j++) {
				v[i].element[j] = m[i][j];
			}
		}
		return v;
	}

	public Numeric transpose() {
		Matrix m = newInstance(new Numeric[cols][rows]);
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				m.m[j][i] = this.m[i][j];
			}
		}
		return m;
	}

	public Numeric trace() {
		Numeric s = Real.ZERO;
		for (int i = 0; i < rows; i++) {
			s = s.add(m[i][i]);
		}
		return s;
	}

	@Nonnull
	public Numeric inverse() {
		Matrix m = newInstance();
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < rows; j++) {
				m.m[i][j] = inverseElement(i, j);
			}
		}
		return m.transpose().divide(determinant());
	}

	Numeric inverseElement(int k, int l) {
		final Matrix result = newInstance();

		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < rows; j++) {
				if (i == k) {
					result.m[i][j] = Real.valueOf(j == l ? 1 : 0);
				} else {
					result.m[i][j] = this.m[i][j];
				}
			}
		}

		return result.determinant();
	}

	public Numeric determinant() {
		if (rows > 1) {
			Numeric a = Real.ZERO;
			for (int i = 0; i < rows; i++) {
				if (m[i][0].signum() != 0) {
					Matrix m = newInstance(new Numeric[rows - 1][rows - 1]);
					for (int j = 0; j < rows - 1; j++) {
						for (int k = 0; k < rows - 1; k++) m.m[j][k] = this.m[j < i ? j : j + 1][k + 1];
					}
					if (i % 2 == 0) {
						a = a.add(this.m[i][0].multiply(m.determinant()));
					} else {
						a = a.subtract(this.m[i][0].multiply(m.determinant()));
					}
				}
			}
			return a;
		} else if (rows > 0) return m[0][0];
		else return Real.ZERO;
	}

	@Nonnull
	public Numeric ln() {
		throw new ArithmeticException();
	}

	@Nonnull
	@Override
	public Numeric lg() {
		throw new ArithmeticException();
	}

	@Nonnull
	public Numeric exp() {
		throw new ArithmeticException();
	}

	public Numeric conjugate() {
		Matrix m = newInstance();
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < cols; j++) {
				m.m[i][j] = this.m[i][j].conjugate();
			}
		}
		return m;
	}

	public int compareTo(Matrix matrix) {
		return ArrayComparator.comparator.compare(vectors(), matrix.vectors());
	}

	public int compareTo(Numeric numeric) {
		if (numeric instanceof Matrix) {
			return compareTo((Matrix) numeric);
		} else {
			return compareTo(valueOf(numeric));
		}
	}

	public static Matrix identity(int dimension) {
		return identity(dimension, dimension);
	}

	public static Matrix identity(int n, int p) {
		Matrix m = new Matrix(new Numeric[n][p]);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < p; j++) {
				if (i == j) {
					m.m[i][j] = Real.ONE;
				} else {
					m.m[i][j] = Real.ZERO;
				}
			}
		}
		return m;
	}

	public String toString() {
		final StringBuilder result = new StringBuilder();
		result.append("{");
		for (int i = 0; i < rows; i++) {
			result.append("{");
			for (int j = 0; j < cols; j++) {
				result.append(m[i][j]).append(j < cols - 1 ? ", " : "");
			}
			result.append("}").append(i < rows - 1 ? ",\n" : "");
		}
		result.append("}");
		return result.toString();
	}

	protected Matrix newInstance() {
		return newInstance(new Numeric[rows][cols]);
	}

	protected Matrix newInstance(Numeric element[][]) {
		return new Matrix(element);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy