/* * Copyright 2011-2013, by Vladimir Kostyukov and Contributors. * * This file is part of la4j project (http://la4j.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * You may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Contributor(s): - * */ package org.la4j.vector.dense; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; import org.la4j.Vector; import org.la4j.Vectors; import org.la4j.vector.DenseVector; import org.la4j.vector.VectorFactory; /** * A basic dense vector implementation using an array. * * A dense data structure stores data in an underlying array. Even zero elements * take up memory space. If you want a data structure that will not have zero * elements take up memory space, try a sparse structure. * * However, fetch/store operations on dense data structures only take O(1) time, * instead of the O(log n) time on sparse structures. * * {@code BasicVector} stores the underlying data in a standard array. */ public class BasicVector extends DenseVector { private static final byte VECTOR_TAG = (byte) 0x00; private double[] self; public BasicVector() { this(0); } public BasicVector(int length) { this(new double[length]); } public BasicVector(double[] array) { super(array.length); this.self = array; } /** * Creates a zero {@link BasicVector} of the given {@code length}. */ public static BasicVector zero(int length) { return new BasicVector(length); } /** * Creates a constant {@link BasicVector} of the given {@code length} with * the given {@code value}. */ public static BasicVector constant(int length, double value) { double[] array = new double[length]; Arrays.fill(array, value); return new BasicVector(array); } /** * Creates an unit {@link BasicVector} of the given {@code length}. */ public static BasicVector unit(int length) { return BasicVector.constant(length, 1.0); } /** * Creates a random {@link BasicVector} of the given {@code length} with * the given {@code Random}. */ public static BasicVector random(int length, Random random) { double[] array = new double[length]; for (int i = 0; i < length; i++) { array[i] = random.nextDouble(); } return new BasicVector(array); } /** * Creates a new {@link BasicVector} from the given {@code array} w/o * copying the underlying array. */ public static BasicVector fromArray(double[] array) { return new BasicVector(array); } /** * Decodes {@link BasicVector} from the given byte {@code array}. * * @param array the byte array representing a vector * * @return a decoded vector */ public static BasicVector fromBinary(byte[] array) { ByteBuffer buffer = ByteBuffer.wrap(array); if (buffer.get() != VECTOR_TAG) { throw new IllegalArgumentException("Can not decode BasicVector from the given byte array."); } double[] values = new double[buffer.getInt()]; for (int i = 0; i < values.length; i++) { values[i] = buffer.getDouble(); } return new BasicVector(values); } /** * Parses {@link BasicVector} from the given CSV string. * * @param csv the CSV string representing a vector * * @return a parsed vector */ public static BasicVector fromCSV(String csv) { return Vector.fromCSV(csv).to(Vectors.BASIC); } /** * Parses {@link BasicVector} from the given Matrix Market string. * * @param mm the string in Matrix Market format * * @return a parsed vector */ public static BasicVector fromMatrixMarket(String mm) { return Vector.fromMatrixMarket(mm).to(Vectors.BASIC); } /** * Creates new {@link BasicVector} from * * @param list list containing doubles * * @return new vector from given double list */ public static BasicVector fromCollection(Collection<? extends Number> list) { //TODO goto lambdas double[] self = new double[list.size()]; int i = 0; for (Number x : list) { self[i] = x.doubleValue(); i++; } return fromArray(self); } /** * Creates new {@link BasicVector} from index-value map * * @param map index-value map * * @param length vector length * * @return created vector */ public static BasicVector fromMap(Map<Integer, ? extends Number> map, int length) { return Vector.fromMap(map, length).to(Vectors.BASIC); } @Override public double get(int i) { return self[i]; } @Override public void set(int i, double value) { self[i] = value; } @Override public void swapElements(int i, int j) { if (i != j) { double d = self[i]; self[i] = self[j]; self[j] = d; } } @Override public Vector copyOfLength(int length) { ensureLengthIsCorrect(length); double[] $self = new double[length]; System.arraycopy(self, 0, $self, 0, Math.min($self.length, self.length)); return new BasicVector($self); } @Override public double[] toArray() { double[] result = new double[length]; System.arraycopy(self, 0, result, 0, length); return result; } @Override public <T extends Vector> T to(VectorFactory<T> factory) { if (factory.outputClass == BasicVector.class) { return factory.outputClass.cast(this); } return super.to(factory); } @Override public Vector blankOfLength(int length) { return BasicVector.zero(length); } @Override public byte[] toBinary() { int size = 1 + // 1 byte: class tag 4 + // 4 bytes: length (8 * length); // 8 * length bytes: values ByteBuffer buffer = ByteBuffer.allocate(size); buffer.put(VECTOR_TAG); buffer.putInt(length); for (double value: self) { buffer.putDouble(value); } return buffer.array(); } }