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

mikera.matrixx.impl.ABandedMatrix Maven / Gradle / Ivy

Go to download

Fast double-precision vector and matrix maths library for Java, supporting N-dimensional numeric arrays.

There is a newer version: 0.67.0
Show newest version
package mikera.matrixx.impl;

import java.util.Arrays;

import mikera.matrixx.AMatrix;
import mikera.matrixx.Matrix;
import mikera.vectorz.AVector;
import mikera.vectorz.impl.ASizedVector;
import mikera.vectorz.util.DoubleArrays;
import mikera.vectorz.util.VectorzException;

/** 
 * Abstract base class for banded matrices
 * 
 * Banded matrix implementations are assumed to store their data efficiently in diagonal bands,
 * so functions on banded matrices can be designed to exploit this fact.
 * 
 * May be either square or rectangular
 * 
 * @author Mike
 *
 */
public abstract class ABandedMatrix extends AMatrix implements IFastBands {
	private static final long serialVersionUID = -229314208418131186L;

	@Override
	public abstract int upperBandwidthLimit();
	
	@Override
	public abstract int lowerBandwidthLimit();
	
	@Override
	public abstract AVector getBand(int band);
	
	@Override
	public int upperBandwidth() {
		for (int i=upperBandwidthLimit(); i>0; i--) {
			if (!(getBand(i).isZero())) return i;
		}
		return 0;
	}
	
	@Override
	public int lowerBandwidth() {
		for (int i=-lowerBandwidthLimit(); i<0; i++) {
			if (!(getBand(i).isZero())) return -i;
		}
		return 0;
	}
	
	@Override
	public boolean isMutable() {
		int lb=lowerBandwidthLimit(), ub=upperBandwidthLimit();
		for (int i=-lb; i<=ub; i++) {
			if (getBand(i).isMutable()) return true;
		}
		return false;
	}
	
	@Override
	public boolean isFullyMutable() {
		return false;
	}
	
	@Override
	public boolean isSymmetric() {
		if (rowCount()!=columnCount()) return false;
		int bs=Math.max(upperBandwidthLimit(), lowerBandwidthLimit());
		for (int i=1; i<=bs; i++) {
			if (!getBand(i).equals(getBand(-i))) return false;
		}
		return true;
	}
	
	@Override
	public boolean isUpperTriangular() {
		return (lowerBandwidthLimit()==0)||(lowerBandwidth()==0);
	}
	
	@Override
	public boolean isLowerTriangular() {
		return (upperBandwidthLimit()==0)||(upperBandwidth()==0);
	}
	
	@Override
	public AVector getRowView(int row) {
		checkRow(row);
		return new BandedMatrixRow(row);
	}
	
	@Override
	public void copyRowTo(int row, double[] dest, int destOffset) {
		int cc=columnCount();
		Arrays.fill(dest, destOffset,destOffset+cc,0.0);
		int start=Math.max(-row, -lowerBandwidthLimit());
		int end=Math.min(cc-1-row, upperBandwidthLimit());
		for (int b=start; b<=end; b++) {
			dest[destOffset+row+b]=unsafeGet(row,row+b);
		}
	}
	
	@Override 
	public long nonZeroCount() {
		long t=0;
		for (int i=-lowerBandwidthLimit(); i<=upperBandwidthLimit(); i++) {
			t+=getBand(i).nonZeroCount();
		}
		return t;
	}
	
	@Override 
	public boolean isZero() {
		for (int i=-lowerBandwidthLimit(); i<=upperBandwidthLimit(); i++) {
			if (!getBand(i).isZero()) return false;
		}
		return true;
	}
	
	@Override
	public boolean isSparse() {
		return (lowerBandwidthLimit()<(rowCount()-1))||(upperBandwidthLimit()<(columnCount()-1));
	}
	
	@Override 
	public double elementSum() {
		double t=0;
		for (int i=-lowerBandwidthLimit(); i<=upperBandwidthLimit(); i++) {
			t+=getBand(i).elementSum();
		}
		return t;
	}
	
	@Override
	public double trace() {
		return getBand(0).elementSum();
	}
	
	@Override
	public double diagonalProduct() {
		return getBand(0).elementProduct();
	}
	
	@Override 
	public double elementSquaredSum() {
		double t=0;
		for (int i=-lowerBandwidthLimit(); i<=upperBandwidthLimit(); i++) {
			t+=getBand(i).elementSquaredSum();
		}
		return t;
	}
	
	@Override 
	public void fill(double value) {
		for (int i=-rowCount()+1; iupper)) return 0;
			return getBand(b).unsafeGet(Math.min(i, row));
		}
		
		@Override 
		public double dotProduct(AVector v) {
			double result=0.0;
			for (int i=Math.max(0,lower+row); i<=Math.min(length-1, row+upper);i++) {
				result+=getBand(i-row).unsafeGet(Math.min(i, row))*v.unsafeGet(i);
			}
			return result;
		}

		@Override
		public void set(int i, double value) {
			checkIndex(i);
			unsafeSet(i,value);
		}
		
		@Override
		public void unsafeSet(int i, double value) {
			int b=i-row;
			getBand(b).unsafeSet(Math.min(i, row),value);
		}

		@Override
		public AVector exactClone() {
			return ABandedMatrix.this.exactClone().getRowView(row);
		}
	
		@Override
		public boolean isFullyMutable() {
			return ABandedMatrix.this.isFullyMutable();
		}
		
		@Override
		public boolean isMutable() {
			return ABandedMatrix.this.isMutable();
		}
		
		@Override
		public double dotProduct(double[] data, int offset) {
			double result=0.0;
			for (int i=0; i=columnCount()) throw new VectorzException("Invalid upper limit: "+maxBand);
		for (int i=minBand; i<=maxBand; i++) {
			AVector v=getBand(i);
			if (bandLength(i)!=v.length()) throw new VectorzException("Invalid band length: "+i);
		}
	}

	@Override
	public double density() {
		return nonZeroCount()/((double)elementCount());
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy