Package mikera.matrixx.impl

Source Code of mikera.matrixx.impl.QuadtreeMatrix

package mikera.matrixx.impl;

import mikera.arrayz.ISparse;
import mikera.matrixx.AMatrix;
import mikera.vectorz.AVector;
import mikera.vectorz.util.ErrorMessages;

/**
* A matrix implemented as a quadtree of submatrices.
*
* Useful for large matrices with heirarchical structure where large regions are either fully sparse
* or of a specialised subtype (e.g. a diagonal matrix).
*
* @author Mike
*
*/
public class QuadtreeMatrix extends ABlockMatrix implements ISparse {
  private static final long serialVersionUID = -7267626771473908891L;

  // Quadtree subcompoents
  private final AMatrix c00, c01, c10, c11;
 
  private final int rowSplit;
  private final int columnSplit;
  private final int rows;
  private final int cols;
 
  private QuadtreeMatrix(AMatrix c00, AMatrix c01, AMatrix c10, AMatrix c11) {
    this.c00=c00;
    this.c01=c01;
    this.c10=c10;
    this.c11=c11;
    this.rowSplit= c00.rowCount();
    this.columnSplit=c00.columnCount();
    this.rows=rowSplit+c10.rowCount();
    this.cols=columnSplit+c01.columnCount();
  }
 
  public static QuadtreeMatrix create(AMatrix c00, AMatrix c01, AMatrix c10, AMatrix c11) {
    if (c00.rowCount()!=c01.rowCount()) throw new IllegalArgumentException("Mismtached submatrix size");
    if (c10.rowCount()!=c11.rowCount()) throw new IllegalArgumentException("Mismtached submatrix size");
    if (c00.columnCount()!=c10.columnCount()) throw new IllegalArgumentException("Mismtached submatrix size");
    if (c01.columnCount()!=c11.columnCount()) throw new IllegalArgumentException("Mismtached submatrix size");
    return new QuadtreeMatrix(c00,c01,c10,c11);
  }
 
  @Override
  public boolean isFullyMutable() {
    return c00.isFullyMutable()&&c01.isFullyMutable()&&c10.isFullyMutable()&&(c11.isFullyMutable());
  }
 
  @Override
  public boolean isMutable() {
    return (c00.isMutable())||(c01.isMutable())||(c10.isMutable())||(c11.isMutable());
  }
 
  @Override
  public boolean isZero() {
    return c00.isZero()&&c01.isZero()&&c10.isZero()&&(c11.isZero());
  }
 
  @Override
  public boolean isDiagonal() {
    if (!isSquare()) return false;
    if (columnSplit==rowSplit) {
      return (c01.isZero())&&(c10.isZero())&&(c00.isDiagonal())&&(c11.isDiagonal());
    } else {
      return super.isDiagonal();
    }
  }

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

  @Override
  public int columnCount() {
    return cols;
  }

  @Override
  public double get(int row, int column) {
    if ((row<0)||(row>=rows)||(column<0)||(column>=cols)) {
      throw new IndexOutOfBoundsException(ErrorMessages.invalidIndex(this, row,column));
    }
    return unsafeGet(row,column);
  }

  @Override
  public void set(int row, int column, double value) {
    if ((row<0)||(row>=rows)||(column<0)||(column>=cols)) {
      throw new IndexOutOfBoundsException(ErrorMessages.invalidIndex(this, row,column));
    }
    unsafeSet(row,column,value);
  }
 
  @Override
  public double unsafeGet(int row, int column) {
    if (row<rowSplit) {
      if (column<columnSplit) {
        return c00.unsafeGet(row,column);
      } else {
        return c01.unsafeGet(row,column-columnSplit);   
      }
    } else {
      if (column<columnSplit) {
        return c10.unsafeGet(row-rowSplit,column);
      } else {
        return c11.unsafeGet(row-rowSplit,column-columnSplit);   
     
    }
  }

  @Override
  public void unsafeSet(int row, int column, double value) {
    if (row<rowSplit) {
      if (column<columnSplit) {
        c00.unsafeSet(row,column, value);
      } else {
        c01.unsafeSet(row,column-columnSplit, value);   
      }
    } else {
      if (column<columnSplit) {
        c10.unsafeSet(row-rowSplit,column, value);
      } else {
        c11.unsafeSet(row-rowSplit,column-columnSplit, value);   
     
    } 
  }
 

  @Override
  public void addAt(int row, int column, double value) {
    if (row<rowSplit) {
      if (column<columnSplit) {
        c00.addAt(row,column, value);
      } else {
        c01.addAt(row,column-columnSplit, value);   
      }
    } else {
      if (column<columnSplit) {
        c10.addAt(row-rowSplit,column, value);
      } else {
        c11.addAt(row-rowSplit,column-columnSplit, value);   
     
    } 
  }
 
  @Override
  public void copyRowTo(int row, double[] data, int offset) {
    if (row<rowSplit) {
      c00.copyRowTo(row, data, offset);
      c01.copyRowTo(row, data, offset+columnSplit);
    } else {
      c10.copyRowTo(row-rowSplit, data, offset);
      c11.copyRowTo(row-rowSplit, data, offset+columnSplit);
    }
  }
 
  @Override
  public void copyColumnTo(int col, double[] data, int offset) {
    if (col<columnSplit) {
      c00.copyRowTo(col, data, offset);
      c10.copyRowTo(col, data, offset+rowSplit);
    } else {
      c01.copyRowTo(col-columnSplit, data, offset);
      c11.copyRowTo(col-columnSplit, data, offset+rowSplit);
    }
  }
 
  @Override
  public long nonZeroCount() {
    return c00.nonZeroCount()+c01.nonZeroCount()+c10.nonZeroCount()+c11.nonZeroCount();
  }
 
  @Override
  public double elementSum() {
    return c00.elementSum()+c01.elementSum()+c10.elementSum()+c11.elementSum();
  }
 
  @Override
  public double elementMin() {
    return Math.min(
        Math.min(c00.elementMin(), c01.elementMin()),
        Math.min(c10.elementMin(), c11.elementMin()));
  }
 
  @Override
  public double elementMax() {
    return Math.max(
        Math.max(c00.elementMax(), c01.elementMax()),
        Math.max(c10.elementMax(), c11.elementMax()));
  }
 
  @Override
  public void fill(double v) {
    c00.fill(v);
    c01.fill(v);
    c10.fill(v);
    c11.fill(v);
  }
 
 
  @Override
  public void add(double v) {
    c00.add(v);
    c01.add(v);
    c10.add(v);
    c11.add(v);
  }
 
  @Override
  public void add(AVector v) {
    AVector v0=v.subVector(0, columnSplit);
    AVector v1=v.subVector(columnSplit,cols-columnSplit);
    c00.add(v0);
    c01.add(v1);
    c10.add(v0);
    c11.add(v1);
  }
 
  @Override
  public AVector getRowView(int row) {
    if (row<rowSplit) {
      return c00.getRowView(row).join(c01.getRowView(row));
    } else {
      row-=rowSplit;
      return c10.getRowView(row).join(c11.getRowView(row));
    }
  }
 
  @Override
  public AVector getColumnView(int col) {
    if (col<columnSplit) {
      return c00.getColumnView(col).join(c10.getColumnView(col));
    } else {
      col-=columnSplit;
      return c01.getColumnView(col).join(c11.getColumnView(col));
    }
  }

  @Override
  public AMatrix exactClone() {
    return new QuadtreeMatrix(c00.exactClone(),c01.exactClone(),c10.exactClone(),c11.exactClone());
  }

  @Override
  public double density() {
    return ((double)nonZeroCount())/((long)rows*(long)cols);
  }

  @Override
  public AMatrix getBlock(int rowBlock, int colBlock) {
    switch (rowBlock) {
    case 0:
      switch (colBlock) {
      case 0: return c00;
      case 1: return c01;
      default: throw new IndexOutOfBoundsException("Column Block: "+colBlock);     
      }
    case 1:
      switch (colBlock) {
      case 0: return c10;
      case 1: return c11;
      default: throw new IndexOutOfBoundsException("Column Block: "+colBlock);     
      }
   
    default: throw new IndexOutOfBoundsException("Row Block: "+rowBlock);
    }
  }
 
  public int getBlockColumnStart(int colBlock) {
    switch (colBlock) {
    case 0: return 0;
    case 1: return columnSplit;
    default: throw new IndexOutOfBoundsException("Column Block: "+colBlock);     
    }
  }
 
  public int getBlockRowStart(int rowBlock) {
    switch (rowBlock) {
    case 0: return 0;
    case 1: return rowSplit;
    default: throw new IndexOutOfBoundsException("Row Block: "+rowBlock);     
    }
  }


  @Override
  public int getBlockColumnCount(int colBlock) {
    return (colBlock==0)?columnSplit:(cols-columnSplit);
  }

  @Override
  public int getBlockRowCount(int rowBlock) {
    return (rowBlock==0)?rowSplit:(rows-rowSplit);
  }

  @Override
  public int getColumnBlockIndex(int col) {
    return col<columnSplit?0:1;
  }

  @Override
  public int getRowBlockIndex(int row) {
    return row<rowSplit?0:1;
  }

  @Override
  public int columnBlockCount() {
    return 2;
  }

  @Override
  public int rowBlockCount() {
    return 2;
  }
}
TOP

Related Classes of mikera.matrixx.impl.QuadtreeMatrix

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.