Click here to Skip to main content
15,886,806 members
Articles / Programming Languages / Java

la4j - Linear Algebra for Java

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
14 Nov 2011CPOL2 min read 30.4K   366   9  
Elegant and pure Java matrix library
/*
 * Copyright 2011, Vladimir Kostyukov
 * 
 * This file is part of la4j project (http://la4j.googlecode.com)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *      
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package la4j.matrix;

import la4j.decomposition.MatrixDecompositor;
import la4j.err.MatrixDecompositionException;
import la4j.err.MatrixException;
import la4j.err.MatrixInversionException;
import la4j.factory.Factory;
import la4j.inversion.MatrixInvertor;
import la4j.vector.Vector;

public abstract class AbstractMatrix implements Matrix {
	
	protected int rows;
	protected int columns;
	
	protected Factory factory;
	
	public AbstractMatrix(Factory factory) {

		this.factory = factory;
		
	}

	@Override
	public int rows() {
		return rows;
	}
	
	@Override
	public int columns() {
		return columns;
	}

	@Override
	public Matrix transpose() {
		return transpose(factory);
	}
	
	@Override
	public double determinant() {
		return triangularize().trace();
	}

	@Override
	public Matrix multiply(double value) {
		return multiply(value, factory);
	}
	
	@Override
	public Matrix multiply(double value, Factory factory) {
		
		if (factory == null) throw new NullPointerException();

		Matrix result = factory.createMatrix(rows, columns);
		
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				result.set(i, j, get(i, j) * value);
			}
		}
		
		return result;
	}

	@Override
	public Vector multiply(Vector vector) throws MatrixException {
		return multiply(vector, factory);
	}
	
	@Override
	public Vector multiply(Vector vector, Factory factory) throws MatrixException {
		
		if (vector == null || factory == null) throw new NullPointerException();
		
		if (columns != vector.length()) {
			throw new MatrixException("can not multiply this matrix on vector: wrong dimmentions");
		}
		
		Vector result = factory.createVector(columns);

		for (int i = 0; i < rows; i++) {

			double summand = 0;
			for (int j = 0; j < columns; j++) {
				summand += get(i, j) * vector.get(j);
			}

			result.set(i, summand);
		}

		return result;
	}

	@Override
	public Matrix multiply(Matrix matrix) throws MatrixException {
		return multiply(matrix, factory);
	}
	
	@Override
	public Matrix multiply(Matrix matrix, Factory factory) throws MatrixException {
		
		if (matrix == null || factory == null) throw new NullPointerException();
		
		if (columns != matrix.rows()) {
			throw new MatrixException("can not multiply this matrix: wrong dimmentions");
		}

		Matrix result = factory.createMatrix(rows, columns);
		
		for (int j = 0; j < matrix.columns(); j++) {
			
			Vector thatColumn = matrix.getColumn(j);
			
			for (int i = 0; i < rows; i++) {
				
				Vector thisRow = getRow(i); 

				double summand = 0;
				for (int k = 0; k < columns; k++) {
					summand += thisRow.get(k) * thatColumn.get(k);
				}
				
				result.set(i, j, summand);
			}
		}

		return result;
	}

	@Override
	public Matrix subtract(double value) {
		return subtract(value, factory);
	}
	
	@Override
	public Matrix subtract(double value, Factory factory) {
		return add(-value, factory);
	}
	
	@Override
	public Matrix subtract(Matrix matrix) throws MatrixException {
		return subtract(matrix, factory);
	}
	
	@Override
	public Matrix subtract(Matrix matrix, Factory factory) throws MatrixException {
		return add(matrix.multiply(-1.0), factory);
	}
	
	@Override
	public Matrix add(double value) {
		return add(value, factory);
	}
	
	@Override
	public Matrix add(double value, Factory factory) {

		if (factory == null) throw new NullPointerException();
		
		Matrix result = factory.createMatrix(rows, columns);
		
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				result.set(i, j, get(i, j) + value);
			}
		}
		
		return result;
	}

	@Override
	public Matrix add(Matrix matrix) throws MatrixException {
		return add(matrix, factory);
	}
	
	@Override
	public Matrix add(Matrix matrix, Factory factory) throws MatrixException {
		
		if (matrix == null || factory == null) throw new NullPointerException();
		
		if (rows != matrix.rows() || columns != matrix.columns()) {
			throw new MatrixException("can not sum this matrix: wrong dimmentions");
		}
		
		Matrix result = factory.createMatrix(rows, columns);

		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				result.set(i, j, get(i, j) + matrix.get(i, j));
			}
		}

		return result;
	}

	@Override
	public Matrix div(double value) {
		return div(value, factory);
	}
	
	@Override
	public Matrix div(double value, Factory factory) {
		return multiply(1.0 / value, factory);
	}
	
	@Override
	public double trace() {
		
		double result = 1;

		for (int i = 0; i < rows; i++) {
			result *= get(i, i);
		}

		return result;
	}
	
	@Override
	public boolean isSymmetric() {

		if (rows != columns) return false;
		
		boolean result = true;
		for (int i = 0; i < rows; i++) {
			for (int j = i + 1; j < columns; j++) {
				result = result && (Math.abs(get(i, j) - get(j, i)) < EPS);
			}
		}
		
		return result && rows > 0 && columns > 0;
	}

	@Override
	public boolean isTriangle() {
		
		boolean result = true;
		
		for (int i = 1; i < rows; i++) {
			for (int j = 0; j < i; j++) {
				result = result && (Math.abs(get(i, j)) < EPS);
			}
		}
		
		return result && rows > 0 && columns > 0;
	}
	
	@Override
	public Matrix triangularize() {
		return triangularize(factory); 
	}
	
	@Override
	public Matrix triangularize(Factory factory) {
		
		if (isTriangle()) return this;
		
		if (factory == null) throw new NullPointerException();
		
		Matrix result = factory.createMatrix(rows, columns);
		for (int i = 0; i < rows; i++) {
			for (int j = i + 1; j < rows; j++) {
				
				double c = get(j, i) / get(i, i);

				for (int k = i; k < columns; k++) {
					if (k == i) {
						result.set(j, k, 0.0);
					} else {
						result.set(j, k, get(j, k) - (get(i, k) * c));
					}
				}
			}
		}

		return result;
	}
	
	@Override
	public Matrix[] decompose(MatrixDecompositor decompositor) throws MatrixDecompositionException {
		return decompose(decompositor, factory);
	}

	@Override
	public Matrix[] decompose(MatrixDecompositor decompositor, Factory factory) throws MatrixDecompositionException {
		return decompositor.decompose(this, factory);
	}

	@Override
	public Matrix inverse(MatrixInvertor invertor) 	throws MatrixInversionException {
		return inverse(invertor, factory);
	}

	@Override
	public Matrix inverse(MatrixInvertor invertor, Factory factory) throws MatrixInversionException {
		return invertor.inverse(this, factory);
	}

	@Override
	public Matrix blank() {
		return blank(factory);
	}
	
	@Override
	public Matrix blank(Factory factory) {
		
		if (factory == null) throw new NullPointerException();
		
		return factory.createMatrix(rows, columns);
	}
	
	@Override
	public Matrix copy() {
		return copy(factory);
	}

	@Override
	public Matrix copy(Factory factory) {

		if (factory == null) throw new NullPointerException();
		
		Matrix result = factory.createMatrix(rows, columns);
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				result.set(i, j, get(i, j));
			}
		}
		
		return result;
	}

	@Override
	public int hashCode() {
		
		int result = 17;
		
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				long value = (long) get(i, j);
				result = 37 * result + (int) (value ^ (value >>> 32));
			}
		}
		
		return result;
	}

	@Override
	public boolean equals(Object object) {

		if (this == object) return true;
		if (object == null) return false;
		if (!(object instanceof Matrix)) return false;
		
		Matrix matrix = (Matrix) object;
		
		if (rows != matrix.rows() || columns != matrix.columns()) return false;
		
		boolean result = true;
		for (int i = 0; result && i < rows; i++) {
			for (int j = 0; result && j < columns; j++) {
				result = result & (Math.abs(get(i, j) - matrix.get(i, j)) < EPS);
			}
		}

		return result;
	}

	@Override
	public String toString() {
		
		StringBuilder sb = new StringBuilder();
		
		for (int i = 0; i < rows; i++) {
			for (int j = 0; j < columns; j++) {
				sb.append(String.format("%8.3f", get(i, j)));
			}
			sb.append("\n");
		}

		return sb.toString();
	}

	@Override
	public Matrix clone() {
		try {
			return (Matrix) super.clone();
		} catch (CloneNotSupportedException ex) {
			throw new InternalError();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Intel
Russian Federation Russian Federation
I've received a Master's Degree in Computer Science at the IT Faculty of Altai State Technical University, Russia.

Currently, I am Software Engineer at Intel Corporation.

Comments and Discussions