Package mikera.vectorz

Source Code of mikera.vectorz.Vectorz$ParserConfigHolder

package mikera.vectorz;

import java.nio.DoubleBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import mikera.arrayz.INDArray;
import mikera.util.Rand;
import mikera.vectorz.impl.ADenseArrayVector;
import mikera.vectorz.impl.AStridedVector;
import mikera.vectorz.impl.ArraySubVector;
import mikera.vectorz.impl.AxisVector;
import mikera.vectorz.impl.RepeatedElementVector;
import mikera.vectorz.impl.SingleElementVector;
import mikera.vectorz.impl.SparseHashedVector;
import mikera.vectorz.impl.SparseIndexedVector;
import mikera.vectorz.impl.StridedVector;
import mikera.vectorz.impl.Vector0;
import mikera.vectorz.impl.ZeroVector;
import mikera.vectorz.util.VectorBuilder;
import mikera.vectorz.util.VectorzException;
import us.bpsm.edn.parser.CollectionBuilder;
import us.bpsm.edn.parser.Parser;
import us.bpsm.edn.parser.Parsers;

public class Vectorz {
  /**
   * Constant tolerance used for testing double values
   */
  public static final double TEST_EPSILON = 0.0000001;
 
  /**
   * Specified the minimum length at which it is worthwhile creating sparse vectors rather than
   * dense vectors. This acts as a hint to modify the behaviour of sparse vector construction functions.
   */
  public static final int MIN_SPARSE_LENGTH=50;
  public static final int BIG_SPARSE_LENGTH=1000000;

  // threshold below which it is worthwhile making big vectors sparse
  private static final double SPARSE_DENSITY_THRESHOLD = 0.2;

  // ===========================
  // Factory functions
 

  public static AVector create(double... data) {
    switch (data.length) {
      case 0: return Vector0.INSTANCE;
      case 1: return Vector1.of(data);
      case 2: return Vector2.of(data);
      case 3: return Vector3.of(data);
      case 4: return Vector4.of(data);
      default: return Vector.of(data);
    }
  }
 
  /**
   * Creates a joined vector that refers to the two underlying vectors
   *
   * @param first
   * @param second
   * @return
   */
  public static AVector join(AVector first, AVector second) {
    AVector result=first.join(second);
    assert(result.length()==first.length()+second.length());
    return result;
  }
 
  public static AVector join(AVector... vectors) {
    AVector result=vectors[0];
    for (int i=1; i<vectors.length; i++) {
      result=result.join(vectors[i]);
    }
    return result;
  }
 
  public static AVector join(List<AVector> vectors) {
    int count=vectors.size();
    AVector v=vectors.get(0);
    for (int i=1; i<count; i++) {
      v=v.join(vectors.get(i));
    }
    return v;
  }
 
  /**
   * Creates an immutable zero vector of the specified length.
   * @param length
   * @return
   */
  public static AVector createZeroVector(int length) {
    if (length==0) return Vector0.INSTANCE;
    return ZeroVector.create(length);
  }
 
  public static Vector wrap(double[] data) {
    return Vector.wrap(data);
  }
 
  public static AVector wrap(double[][] data) {
    if ((data.length)==0) return Vector0.INSTANCE;
   
    AVector v=wrap(data[0]);
    for (int i=1; i<data.length; i++) {
      v=join(v,wrap(data[i]));
    }
    return v;
  }
 
  public static ADenseArrayVector wrap(double[] data, int offset, int length) {
    if ((offset==0)&&(length==data.length)) return wrap(data);
    return ArraySubVector.wrap(data, offset, length);
  }
 
  public static AStridedVector wrapStrided(double[] data, int offset, int length, int stride) {
    if (stride==1) {
      if ((offset==0)&&(length==data.length)) {
        return Vector.wrap(data);
      }
      return ArraySubVector.wrap(data, offset, length);
    }
    return StridedVector.wrapStrided(data,offset,length,stride);
  }

  /**
   * Returns a new mutable vector filled with zeros of the specified length.
   *
   * Attempts to select the most efficient mutable concrete Vector type for any given length.
   * @param length
   * @return
   */
  public static AVector newVector(int length) {
    switch (length) {
      case 0: return Vector0.INSTANCE;
      case 1: return new Vector1();
      case 2: return new Vector2();
      case 3: return new Vector3();
      case 4: return new Vector4();
    }
    if (length>=BIG_SPARSE_LENGTH) return createSparseMutable(length);
    return Vector.createLength(length);
  }
 
  /**
   * Creates a sparse vector from the data in the given vector. Selects the appropriate sparse
   * vector type based on analysis of the element values.
   *
   * @param v Vector containing sparse element data
   * @return
   */
  public static AVector createSparse(AVector v) {
    int len=v.length();
    long n=v.nonZeroCount();
    if (n==0) {
      return createZeroVector(len);
    } else if (n==1) {
      for (int i=0; i<len; i++) {
        double val=v.unsafeGet(i);
        if (val!=0.0) {
          if (val==1.0) {
            return AxisVector.create(i, len);
          } else {
            return SingleElementVector.create(val,i,len);
          }
        }
      }
      throw new VectorzException("non-zero element not found!!");
    } else if (n>(len*SPARSE_DENSITY_THRESHOLD)) {
      return Vector.create(v); // not enough sparsity to make worthwhile
    } else {
      return SparseIndexedVector.create(v);
    }
  }
 
  public static AVector createSparseMutable(int length) {
    if (length<MIN_SPARSE_LENGTH) {
      return Vector.createLength(length); // not enough sparsity to make worthwhile
    } else  {
      return SparseHashedVector.createLength(length);
    }
  }
 
  public static AVector createSparseMutable(AVector v) {
    int len=v.length();
    long n=v.nonZeroCount();
   
    if ((len<MIN_SPARSE_LENGTH)||(n>(len*SPARSE_DENSITY_THRESHOLD))) {
      return Vector.create(v); // not enough sparsity to make worthwhile, just copy
    } else {
      return SparseIndexedVector.create(v);
    }
  }

  /**
   * Creates a new zero-filled vector of the same size as the given Vector.
   * @param v
   * @return
   */
  public static AVector createSameSize(AVector v) {
    return newVector(v.length());
  }

  /**
   * Creates a mutable clone of a given vector
   * @param vector
   * @return
   */
  public static AVector create(AVector vector) {
    return vector.clone();
 
 
  /**
   * Creates a mutable clone of a given vector
   * @param vector
   * @return
   */
  public static AVector create(IVector vector) {
    return (AVector)vector.clone();
 

  public static Scalar createScalar(double value) {
    return new Scalar(value);
 
 
  static void copy(AVector source, int srcOffset, AVector dest, int destOffset, int length) {
    source.copyTo(srcOffset, dest, destOffset, length);
  }

  public static AVector createUniformRandomVector(int dimensions) {
    AVector v=Vectorz.newVector(dimensions);
    for (int i=0; i<dimensions; i++) {
      v.unsafeSet(i,Rand.nextDouble());
    }
    return v;
  }

  public static AVector createMutableVector(AVector v) {
    return v.clone();
  }
 
  /**
   * Returns an immutable vector of zeros
   * @param dimensions
   * @return
   */
  public static AVector immutableZeroVector(int dimensions) {
    return ZeroVector.create(dimensions);
  }
 
  // ====================================
  // Edn formatting and parsing functions
 
  private static class ParserConfigHolder {
    static final Parser.Config parserConfig;
    static {
      us.bpsm.edn.parser.Parser.Config.Builder b= us.bpsm.edn.parser.Parsers.newParserConfigBuilder();
      b.setVectorFactory(new us.bpsm.edn.parser.CollectionBuilder.Factory() {
        @Override
        public us.bpsm.edn.parser.CollectionBuilder builder() {
          return new CollectionBuilder() {
            VectorBuilder b=new VectorBuilder();
            @Override
            public void add(Object o) {
              double d;
              if (o instanceof Double) {
                d=(Double)o;
              } else if (o instanceof Number) {
                d=((Number)o).doubleValue();
              } else {
                throw new VectorzException("Cannot parse double value from class: "+o.getClass());
              }
              b.append(d);
            }

            @Override
            public Object build() {
              return b.toVector();
            }         
          };
        }}
      );
      parserConfig=b.build();
    }
  }
 
  private static Parser.Config getVectorParserConfig() {
    return ParserConfigHolder.parserConfig;
  }
 
  /**
   * Parse a vector in edn format
   * @param ednString
   * @return
   */
  public static AVector parse(String ednString) {
    Parser p=Parsers.newParser(getVectorParserConfig());
    return (AVector)p.nextValue(Parsers.newParseable(ednString));
  }

  /**
   * Create a vector from a list of numerical values (objects should be java.lang.Number instances)
   */
  public static AVector create(List<Object> d) {
    int length=d.size();
    AVector v=Vectorz.newVector(length);
    for (int i=0; i<length; i++) {
      v.set(i,Tools.toDouble(d.get(i)));
    }
    return v;
  }
 
  /**
   * Create a vector from a DoubleBuffer
   * Note: consumes all doubles from the buffer
   */
  public static AVector create(DoubleBuffer d) {
    int length=d.remaining();
    Vector v=Vector.createLength(length);
    double[] data=v.getArray();
    d.get(data, 0, length);
    return v;
  }
 
  /**
   * Create a vector from an arbitrary iterable object
   * @param d
   * @return
   */
  public static AVector create(Iterable<Object> d) {
    ArrayList<Object> al=new ArrayList<Object>();
    for (Object o:d) {
      al.add(o);
    }
    return create(al);
  }

  /**
   * Returns the minimum-valued component in a vector
   * @param v
   * @return
   */
  public static double minValue(AVector v) {
    return v.elementMin();
  }
 
  /**
   * Returns the index of the minimum-valued component in a vector
   * @param v
   * @return
   */
  public static int indexOfMinValue(AVector v) {
    int len=v.length();
    double min = v.get(0);
    int ind=0;
    for (int i=1; i<len; i++) {
      double d=v.unsafeGet(i);
      if (d<min) {
        min=d;
        ind=i;
      }
    }
    return ind;
  }
 
  public static double maxValue(AVector v) {
    return v.elementMax();
  }
 
  public static int indexOfMaxValue(AVector v) {
    int len=v.length();
    double max = v.unsafeGet(0);
    int ind=0;
    for (int i=1; i<len; i++) {
      double d=v.get(i);
      if (d>max) {
        max=d;
        ind=i;
      }
    }
    return ind;
  }
 
  public static void invSqrt(AVector v) {
    if (v instanceof Vector) {invSqrt((Vector) v); return;}
    int len=v.length();
    for (int i=0; i<len; i++) {
      double d=1.0/Math.sqrt(v.unsafeGet(i));
      v.set(i,d);
    }   
  }
 
  public static void invSqrt(Vector v) {
    int len=v.length();
    double[] data=v.getArray();
    for (int i=0; i<len; i++) {
      double d=1.0/Math.sqrt(data[i]);
      data[i]=d;
    }   
  }
 
  public static double totalValue(AVector v) {
    return v.elementSum();
  }
 
  public static double averageValue(AVector v) {
    int len=v.length();
    double result=v.elementSum();
    return result/len;
  }
 
  public static double averageSquaredDifference(AVector a, AVector b) {
    int len=a.length();
    if (len!=b.length()) throw new IllegalArgumentException("Vector size mismatch");
    double result=0.0;
    for (int i=0; i<len; i++) {
      double d=a.unsafeGet(i)-b.unsafeGet(i);
      result+=d*d;
    }
    return result/len;
  }
 
  public static double rmsDifference(AVector a, AVector b) {
    return Math.sqrt(averageSquaredDifference(a,b));
  }

  /**
   * Fills a vector with uniform random numbers in the range [0..1)
   *
   * @param v
   */
  public static void fillRandom(AVector v) {
    int len=v.length();
    for (int i=0; i<len; i++) {
      v.unsafeSet(i,Rand.nextDouble());
    }
  }
 
  public static void fillGaussian(AVector v) {
    fillGaussian(v,0.0,1.0);
  }
 
  /**
   * Fills a vector with index values
   * @param v
   */
  public static void fillIndexes(AVector v) {
    int n=v.length();
    for (int i=0; i<n; i++) {
      v.unsafeSet(i,i);
    }
  }
 
  public static void fillGaussian(AVector v, double mean, double sd) {
    int len=v.length();
    for (int i=0; i<len; i++) {
      v.unsafeSet(i,mean+Rand.nextGaussian()*sd);
    }
  }
 
  public static void fillBinaryRandom(AVector v) {
    fillBinaryRandom(v,0.5);
  }
 
  public static AVector axisVector(int axisIndex, int dimensions) {
    return AxisVector.create(axisIndex, dimensions);
  }

  public static void fillBinaryRandom(AVector v, double prob) {
    int len=v.length();
    for (int i=0; i<len; i++) {
      v.unsafeSet(i,Rand.binary(prob));
    }
  }

  /**
   * Coerce to AVector
   * @param o
   * @return
   */
  @SuppressWarnings("unchecked")
  public static AVector toVector(Object o) {
    if (o instanceof AVector) {
      return (AVector)o;
    } else if (o instanceof double[]) {
      return Vectorz.create((double[])o);
    } else if (o instanceof INDArray) {
      INDArray a=(INDArray)o;
      if (a.dimensionality()!=1) throw new IllegalArgumentException("Cannot coerce INDArray with shape "+a.getShape().toString()+" to a vector");
      return a.asVector();
    } else if (o instanceof List<?>) {
      return Vectorz.create((List<Object>)o);
    } else if (o instanceof Iterable<?>) {
      return Vectorz.create((Iterable<Object>)o);
    }
    throw new UnsupportedOperationException("Cannot coerce to AVector: "+o.getClass());
  }

  public static AVector create(Object o) {
    if (o instanceof Double) return Vector1.of(Tools.toDouble(o));
    return toVector(o);
  }

  public static AVector createRange(int length) {
    AVector v=Vectorz.newVector(length);
    for (int i=0; i<length; i++) {
      v.unsafeSet(i,i);
    }
    return v;
  }
 
  public static AVector createRepeatedElement(int length,double value) {
    if (length==0) return Vector0.INSTANCE;
    return RepeatedElementVector.create(length, value);
  }

  /**
   * Cast a long to an int value, and throws an exception if the result does not fit in an int
   * @param value
   * @return
   */
  public static int safeLongToInt(long value) {
    int result=(int)value;
    if (result!=value) throw new IllegalArgumentException("Can't cast safely to int: "+value);
    return result;
  }

  /**
   * Fills a mutable vector with random double values in the range [0..1)
   */
  public static void fillRandom(AVector v, long seed) {
    fillRandom(v, new Random(seed));
  }

  /**
   * Fills a mutable vector with random double values in the range [0..1)
   */
  public static void fillRandom(AVector v, Random random) {
    int n=v.length();
    for (int i=0; i<n ; i++) {
      v.unsafeSet(i, random.nextDouble());
    }
  }
 
  /**
   * Fills a mutable vector with random normally distributed values
   */
  public static void fillNormal(AVector v, long seed) {
    fillNormal(v, new Random(seed));

  }

  /**
   * Fills a mutable vector with random normally distributed values
   */
  public static void fillNormal(AVector v, Random random) {
    int n=v.length();
    for (int i=0; i<n ; i++) {
      v.unsafeSet(i, random.nextGaussian());
    }
  }



 
}
TOP

Related Classes of mikera.vectorz.Vectorz$ParserConfigHolder

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.