gov.sandia.cognition.math.matrix.custom.BaseMatrix Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: BaseMatrix.java
* Authors: Jeremy D. Wendt
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright 2015, Sandia Corporation. Under the terms of Contract
* DE-AC04-94AL85000, there is a non-exclusive license for use of this work by
* or on behalf of the U.S. Government. Export of this program may require a
* license from the United States Government. See CopyrightHistory.txt for
* complete details.
*/
package gov.sandia.cognition.math.matrix.custom;
import gov.sandia.cognition.math.matrix.AbstractMatrix;
import gov.sandia.cognition.math.matrix.DimensionalityMismatchException;
import gov.sandia.cognition.math.matrix.Matrix;
import gov.sandia.cognition.math.matrix.MatrixEntry;
import gov.sandia.cognition.math.matrix.Vector;
import java.text.NumberFormat;
import java.util.Iterator;
/**
* This package-private class implements the basic math methods, ensures size
* constraints are met for the operation, and then calls the
* matrix-type-specific (diagonal, dense, sparse) version of the basic matrix
* method.
*
* @author Jeremy D. Wendt
* @since 4.0.0
*/
abstract class BaseMatrix
extends AbstractMatrix
{
/**
* Creates a new {@link BaseMatrix}.
*/
protected BaseMatrix()
{
super();
}
@Override
final public Matrix plus(
final Matrix other)
{
final Matrix result;
if (this instanceof DenseMatrix)
{
result = this.clone();
result.plusEquals(other);
}
else if (other instanceof DenseMatrix)
{
result = other.clone();
result.plusEquals(this);
}
else if (this instanceof SparseMatrix)
{
result = this.clone();
result.plusEquals(other);
}
else if (other instanceof SparseMatrix)
{
result = other.clone();
result.plusEquals(this);
}
else if (this instanceof DiagonalMatrix && other instanceof DiagonalMatrix)
{
result = this.clone();
result.plusEquals(other);
}
else
{
result = this.clone();
result.plusEquals(other);
}
return result;
}
@Override
final public Matrix minus(
final Matrix other)
{
final Matrix result;
if (this instanceof DenseMatrix)
{
result = this.clone();
result.minusEquals(other);
}
else if (other instanceof DenseMatrix)
{
result = other.negative();
result.plusEquals(this);
}
else if (this instanceof SparseMatrix)
{
result = this.clone();
result.minusEquals(other);
}
else if (other instanceof SparseMatrix)
{
result = other.negative();
result.plusEquals(this);
}
else if (this instanceof DiagonalMatrix && other instanceof DiagonalMatrix)
{
result = this.clone();
result.minusEquals(other);
}
else
{
result = this.clone();
result.minusEquals(other);
}
return result;
}
@Override
final public Matrix dotTimes(
final Matrix other)
{
final Matrix result;
if (this instanceof DiagonalMatrix)
{
result = this.clone();
result.dotTimesEquals(other);
}
else if (other instanceof DiagonalMatrix)
{
result = other.clone();
result.dotTimesEquals(this);
}
else if (this instanceof SparseMatrix)
{
result = this.clone();
result.dotTimesEquals(other);
}
else if (other instanceof SparseMatrix)
{
result = other.clone();
result.dotTimesEquals(this);
}
else if (this instanceof DenseMatrix && other instanceof DenseMatrix)
{
result = this.clone();
result.dotTimesEquals(other);
}
else
{
result = this.clone();
result.dotTimesEquals(other);
}
return result;
}
@Override
final public void plusEquals(
final Matrix other)
{
if (other instanceof DiagonalMatrix)
{
plusEquals((DiagonalMatrix) other);
}
else if (other instanceof DenseMatrix)
{
this.plusEquals((DenseMatrix) other);
}
else if (other instanceof SparseMatrix)
{
this.plusEquals((SparseMatrix) other);
}
else
{
super.plusEquals(other);
}
}
/**
* Type-specific version of plusEquals for combining whatever type this is
* with the input sparse matrix.
*
* @param other A sparse matrix to add to this
*/
public abstract void plusEquals(
final SparseMatrix other);
/**
* Type-specific version of plusEquals for combining whatever type this is
* with the input dense matrix.
*
* @param other A dense matrix to add to this
*/
public abstract void plusEquals(
final DenseMatrix other);
/**
* Type-specific version of plusEquals for combining whatever type this is
* with the input diagonal matrix.
*
* @param other A diagonal matrix to add to this
*/
public abstract void plusEquals(
final DiagonalMatrix other);
@Override
final public void scaledPlusEquals(
final double scaleFactor,
final Matrix other)
{
if (other instanceof DiagonalMatrix)
{
scaledPlusEquals((DiagonalMatrix) other, scaleFactor);
}
else if (other instanceof DenseMatrix)
{
this.scaledPlusEquals((DenseMatrix) other, scaleFactor);
}
else if (other instanceof SparseMatrix)
{
this.scaledPlusEquals((SparseMatrix) other, scaleFactor);
}
else
{
super.scaledPlusEquals(scaleFactor, other);
}
}
/**
* Type-specific version of scaledPlusEquals for combining whatever type
* this is with the input sparse matrix.
*
* @param other A sparse matrix to add to this
* @param scaleFactor The amount to scale other by
*/
public abstract void scaledPlusEquals(
final SparseMatrix other,
final double scaleFactor);
/**
* Type-specific version of scaledPlusEquals for combining whatever type
* this is with the input dense matrix.
*
* @param other A dense matrix to add to this
* @param scaleFactor The amount to scale other by
*/
public abstract void scaledPlusEquals(
final DenseMatrix other,
final double scaleFactor);
/**
* Type-specific version of scaledPlusEquals for combining whatever type
* this is with the input diagonal matrix.
*
* @param other A diagonal matrix to add to this
* @param scaleFactor The amount to scale other by
*/
public abstract void scaledPlusEquals(
final DiagonalMatrix other,
final double scaleFactor);
@Override
final public void minusEquals(
final Matrix other)
{
if (other instanceof DiagonalMatrix)
{
minusEquals((DiagonalMatrix) other);
}
else if (other instanceof DenseMatrix)
{
this.minusEquals((DenseMatrix) other);
}
else if (other instanceof SparseMatrix)
{
this.minusEquals((SparseMatrix) other);
}
else
{
super.minusEquals(other);
}
}
/**
* Type-specific version of minusEquals for combining whatever type this is
* with the input sparse matrix.
*
* @param other A sparse matrix to subtract from this
*/
public abstract void minusEquals(
final SparseMatrix other);
/**
* Type-specific version of minusEquals for combining whatever type this is
* with the input dense matrix.
*
* @param other A dense matrix to subtract from this
*/
public abstract void minusEquals(
final DenseMatrix other);
/**
* Type-specific version of minusEquals for combining whatever type this is
* with the input diagonal matrix.
*
* @param other A diagonal matrix to subtract from this
*/
public abstract void minusEquals(
final DiagonalMatrix other);
@Override
final public void dotTimesEquals(
final Matrix other)
{
if (other instanceof DiagonalMatrix)
{
dotTimesEquals((DiagonalMatrix) other);
}
else if (other instanceof DenseMatrix)
{
this.dotTimesEquals((DenseMatrix) other);
}
else if (other instanceof SparseMatrix)
{
this.dotTimesEquals((SparseMatrix) other);
}
else
{
super.dotTimesEquals(other);
}
}
/**
* Type-specific version of dotTimesEquals for combining whatever type this
* is with the input sparse matrix.
*
* @param other A sparse matrix to dot with this
*/
public abstract void dotTimesEquals(
final SparseMatrix other);
/**
* Type-specific version of dotTimesEquals for combining whatever type this
* is with the input dense matrix.
*
* @param other A dense matrix to dot with this
*/
public abstract void dotTimesEquals(
final DenseMatrix other);
/**
* Type-specific version of dotTimesEquals for combining whatever type this
* is with the input diagonal matrix.
*
* @param other A diagonal matrix to dot with this
*/
public abstract void dotTimesEquals(
final DiagonalMatrix other);
@Override
final public Matrix times(
final Matrix other)
{
if (other instanceof DiagonalMatrix)
{
return this.times((DiagonalMatrix) other);
}
else if (other instanceof DenseMatrix)
{
return this.times((DenseMatrix) other);
}
else if (other instanceof SparseMatrix)
{
return this.times((SparseMatrix) other);
}
else
{
return super.times(other);
}
}
/**
* Type-specific version of times for combining whatever type this is with
* the input sparse matrix.
*
* @param other A sparse matrix to multiply with this
*/
public abstract Matrix times(
final SparseMatrix other);
/**
* Type-specific version of times for combining whatever type this is with
* the input dense matrix.
*
* @param other A dense matrix to multiply with this
*/
public abstract Matrix times(
final DenseMatrix other);
/**
* Type-specific version of times for combining whatever type this is with
* the input diagonal matrix.
*
* @param other A diagonal matrix to multiply with this
*/
public abstract Matrix times(
final DiagonalMatrix other);
@Override
final public Vector times(
final Vector vector)
{
if (vector instanceof DenseVector)
{
return times((DenseVector) vector);
}
else if (vector instanceof SparseVector)
{
return this.times((SparseVector) vector);
}
else
{
return super.times(vector);
}
}
/**
* Type-specific version of times for combining whatever type this is with
* the input sparse vector.
*
* @param vector A sparse vector to multiply with this
*/
public abstract Vector times(
final SparseVector vector);
/**
* Type-specific version of times for combining whatever type this is with
* the input dense vector.
*
* @param vector A dense vector to multiply with this
*/
public abstract Vector times(
final DenseVector vector);
/**
* Package-private method that puts the vector * matrix code in the matrix
* class instead of in the vector class (why should vectors know the
* internals of matrices?).
*
* @param vector The vector to pre-multiply this by
* @return The resulting vector from input * this
* @throws DimensionalityMismatchException if the input vectors's dimensions
* doesn't match this's numRows.
*/
public final Vector preTimes(
final Vector vector)
{
if (vector instanceof DenseVector)
{
return preTimes((DenseVector) vector);
}
else if (vector instanceof SparseVector)
{
return this.preTimes((SparseVector) vector);
}
else
{
// Fallback for compatability.
vector.assertDimensionalityEquals(this.getNumRows());
final Vector result = vector.getVectorFactory().createVector(
this.getNumColumns());
for (final MatrixEntry entry : this)
{
result.increment(entry.getColumnIndex(),
entry.getValue() * vector.get(entry.getRowIndex()));
}
return result;
}
}
/**
* Type-specific version of pre-times for combining whatever type this is
* with the input sparse vector.
*
* @param vector A sparse vector to multiply with this
*/
public abstract Vector preTimes(
final SparseVector vector);
/**
* Type-specific version of pre-times for combining whatever type this is
* with the input dense vector.
*
* @param vector A dense vector to multiply with this
*/
public abstract Vector preTimes(
final DenseVector vector);
/**
* Helper method checks that the input submatrix range is acceptable for
* this matrix, including that the max is greater than or equal to the min.
* Note that the input mins and maxs are inclusive.
*
* @param minRow The minimum row to return (inclusive)
* @param maxRow The maximum row to return (inclusive)
* @param minCol The minimum column to return (inclusive)
* @param maxCol The maximum column to return (inclusive)
* @throws ArrayIndexOutOfBoundsException if the input range is illegal or
* outside the bounds of this.
*/
final protected void checkSubmatrixRange(
final int minRow,
final int maxRow,
final int minCol,
final int maxCol)
{
if (maxRow < minRow || maxCol < minCol || minRow < 0 || minCol < 0
|| maxRow
> getNumRows() || maxCol > getNumColumns())
{
throw new ArrayIndexOutOfBoundsException("Input range is invalid: ["
+ minRow + ", " + maxRow + "], [" + minCol + ", " + maxCol + "]");
}
}
/**
* Checks that the input vector has the same dimensionality as this's
* numRows (otherwise, there can be no solution for Ax = b).
*
* @param b The RHS vector
* @throws IllegalArgumentException if the input's size doesn't match this's
* numRows
*/
final protected void checkSolveDimensions(
final Vector b)
{
if (b.getDimensionality() != this.getNumRows())
{
throw new IllegalArgumentException("Input vector (length = "
+ b.getDimensionality()
+ ") can't be \"solved\" with by a matrix with dimensions "
+ getNumRows() + "x" + getNumColumns());
}
}
/**
* Checks that the input matrix has the same numRows as this's numRows
* (otherwise, there can be no soluation for Ax = b).
*
* @param b The RHS matrix
* @throws IllegalArgumentException if the input's size doesn't match this's
* numRows
*/
final protected void checkSolveDimensions(
final Matrix b)
{
if (b.getNumRows() != this.getNumRows())
{
throw new IllegalArgumentException("Input matrix (numRows = "
+ b.getNumRows()
+ ") can't be \"solved\" with by a matrix with dimensions "
+ getNumRows() + "x" + getNumColumns());
}
}
@Override
final public String toString(
final NumberFormat format)
{
StringBuilder sb = new StringBuilder();
int m = getNumRows();
int n = getNumColumns();
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
sb.append(format.format(get(i, j))).append(" ");
}
sb.append('\n');
}
return sb.toString();
}
@Override
public Iterator iterator()
{
return new MatrixIterator(this);
}
}