Package mikera.vectorz.impl

Source Code of mikera.vectorz.impl.SparseImmutableVector

package mikera.vectorz.impl;

import mikera.indexz.Index;
import mikera.matrixx.AMatrix;
import mikera.matrixx.impl.AVectorMatrix;
import mikera.vectorz.AVector;
import mikera.vectorz.Op;
import mikera.vectorz.Vector;
import mikera.vectorz.util.DoubleArrays;
import mikera.vectorz.util.ErrorMessages;
import mikera.vectorz.util.VectorzException;

/**
* Indexed sparse immutable vector
*
* Efficient for sparse vectors. Maintains a indexed array of strictly non-zero elements.
*
* @author Mike
*
*/
public class SparseImmutableVector extends ASparseIndexedVector {
  private static final long serialVersionUID = 750093598603613879L;

  private final Index index;
  private final double[] data;
  private final int dataLength;
 
  private SparseImmutableVector(int length, Index index) {
    this(length,index,new double[index.length()]);
  }
 
  private SparseImmutableVector(int length, Index index, double[] data) {
    super(length);
    this.index=index;
    this.data=data;
    dataLength=data.length;
  }
 
  private SparseImmutableVector(int length, Index index, AVector data) {
    this(length,index,data.toDoubleArray());
  }
 
  /**
   * Creates a SparseImmutableVector with the specified index and data values.
   *
   * WARNING: Performs no checking - Index must be distinct and sorted, and data must be non-zero.
   */
  public static SparseImmutableVector wrap(int length, Index index, double[] data) {
    assert(index.length()==data.length);
    assert(index.isDistinctSorted());
    return new SparseImmutableVector(length, index,data);
  }
 
  @Override
  double[] internalData() {
    return data;
  }

  @Override
  Index internalIndex() {
    return index;
  }
 
  /**
   * Creates a SparseImmutableVector using the given sorted Index to identify the indexes of non-zero values,
   * and a double[] array to specify all the non-zero element values
   */
  public static AVector create(int length, Index index, double[] data) {
    int dataLength=data.length;
    if (!index.isDistinctSorted()) {
      throw new IllegalArgumentException("Index must be sorted and distinct");
    }
    if (!(index.length()==dataLength)) {
      throw new IllegalArgumentException("Length of index: mismatch woth data");     
    }
    if (dataLength==0) return ZeroVector.create(length);
    if (dataLength==length) return ImmutableVector.create(data);
    return new SparseImmutableVector(length, index.clone(),DoubleArrays.copyOf(data));
  }
 
  /**
   * Creates a SparseImmutableVector using the given sorted Index to identify the indexes of non-zero values,
   * and a dense vector to specify all the non-zero element values
   */
  public static AVector create(int length, Index index, AVector data) {
    int dataLength=data.length();
    if (!index.isDistinctSorted()) {
      throw new IllegalArgumentException("Index must be sorted and distinct");
    }
    if (!(index.length()==dataLength)) {
      throw new IllegalArgumentException("Length of index: mismatch woth data");     
    }
    if (dataLength==0) return ZeroVector.create(length);
    if (dataLength==length) return ImmutableVector.create(data);
    return wrap(length, index.clone(), data.toDoubleArray());
  }
 
  /**
   * Creates a SparseIndexedVector from the given vector, ignoring the zeros in the source.
   *
   */
  public static AVector create(AVector source) {
    int length = source.length();
    if (length==0) return Vector0.INSTANCE;
    int dataLength=(int) source.nonZeroCount();
    if (dataLength==length) return ImmutableVector.create(source);
    if (dataLength==0) return ZeroVector.create(length);
   
    int[] indexes=new int[dataLength];
    double[] vals=new double[dataLength];
    int pos=0;
    for (int i=0; i<length; i++) {
      double v=source.unsafeGet(i);
      if (v!=0.0) {
        indexes[pos]=i;
        vals[pos]=v;
        pos++;
      }
    }
    return wrap(length,Index.wrap(indexes),vals);
  }
 
  public static AVector create(ASparseVector source) {
    int length = source.length();
    if (length==0) return Vector0.INSTANCE;
    int[] indexes=source.nonZeroIndices();
    double[] vals=source.nonZeroValues();
    return wrap(length,Index.wrap(indexes),vals);
  }
 
  /** Creates a SparseIndexedVector from a row of an existing matrix */
  public static AVector createFromRow(AMatrix m, int row) {
    if (m instanceof AVectorMatrix) return create(m.getRow(row));
    return create(m.getRow(row));
  }
 
  @Override
  public int nonSparseElementCount() {
    return dataLength;
  }
 
  @Override
  public boolean isZero() {
    // never zero, since we maintain invariant of always having one non-zero value
    return false;
  }
 
  @Override
  public double maxAbsElement() {
    double result=data[0];
    for (int i=1; i<dataLength; i++) {
      double d=Math.abs(data[i]);
      if (d>result) result=d;
    }
    return result;
  }
 
  @Override
  public int maxElementIndex(){
    double result=data[0];
    int di=0;
    for (int i=1; i<dataLength; i++) {
      double d=data[i];
      if (d>result) {
        result=d;
        di=i;
      }
    }
    if (result<0.0) { // need to find a sparse element
      int ind=sparseElementIndex();
      if (ind>0) return ind;
    }
    return index.get(di);
  }
 
  @Override
  public int maxAbsElementIndex(){
    double result=Math.abs(data[0]);
    int di=0;
    for (int i=1; i<dataLength; i++) {
      double d=Math.abs(data[i]);
      if (d>result) {
        result=d;
        di=i;
      }
    }
    return index.get(di);
  }
 
  @Override
  public int minElementIndex(){
    double result=data[0];
    int di=0;
    for (int i=1; i<dataLength; i++) {
      double d=data[i];
      if (d<result) {
        result=d;
        di=i;
      }
    }
    if (result>0.0) { // need to find a sparse element
      int ind=sparseElementIndex();
      if (ind>=0) return ind;
    }
    return index.get(di);
  }
 
  /**
   * Return this index of a sparse zero element, or -1 if not sparse
   * @return
   */
  private int sparseElementIndex() {
    for (int i=0; i<length; i++) {
      if (!index.contains(i)) return i;
    }
    throw new VectorzException(ErrorMessages.impossible());
  }

 
  @Override
  public void negate() {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }
 
  @Override
  public void applyOp(Op op) {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }
 
  @Override
  public void abs() {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }

  @Override
  public double get(int i) {
    checkIndex(i);
    return unsafeGet(i);
  }
 
  @Override
  public double unsafeGet(int i) {
    int ip=index.indexPosition(i);
    if (ip<0) return 0.0;
    return data[ip];
  }
 
  @Override
  public boolean isFullyMutable() {
    return false;
  }
 
  @Override
  public boolean isMutable() {
    return false;
  }
 
  @Override
  public long nonZeroCount() {
    return dataLength;
  }
 
  @Override
  public int[] nonZeroIndices() {
    return index.data.clone();
  }

  @Override
  public void add(ASparseVector v) {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }
 
  @Override
  public void set(AVector v) {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }

  @Override
  public void set(int i, double value) {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));

  }
 
  @Override
  public void addAt(int i, double value) {
    throw new UnsupportedOperationException(ErrorMessages.immutable(this));
  }

  @Override
  public Vector nonSparseValues() {
    return Vector.wrap(data);
  }
 
  @Override
  public double[] nonZeroValues() {
    return DoubleArrays.copyOf(data);
  }
 
  @Override
  public Index nonSparseIndex() {
    return index;
  }

  @Override
  public boolean includesIndex(int i) {
    return index.indexPosition(i)>=0;
  }
 
  @Override
  public Vector dense() {
    Vector v=Vector.createLength(length);
    addToArray(v.data,0);
    return v;
  }
 
  @Override
  public SparseIndexedVector mutable() {
    return SparseIndexedVector.create(length, index, data);
  }
 
  @Override
  public SparseIndexedVector clone() {
    return SparseIndexedVector.create(length, index, data);
  }
 
  @Override
  public SparseIndexedVector sparseClone() {
    return SparseIndexedVector.create(length, index, data);
  }
 
  @Override
  public SparseImmutableVector exactClone() {
    return new SparseImmutableVector(length,index.clone(),data.clone());
  }
 
  @Override
  public void validate() {
    if (data.length==0) throw new VectorzException("SparseImmutableVector must have some non-zero values");
    if (index.length()!=data.length) throw new VectorzException("Inconsistent data and index!");
    if (!index.isDistinctSorted()) throw new VectorzException("Invalid index: "+index);
    for (int i=0; i<data.length; i++) {
      if (data[i]==0) throw new VectorzException("Should be no zero values in data array!");
    }
    super.validate();
  }


}
TOP

Related Classes of mikera.vectorz.impl.SparseImmutableVector

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.