org.apache.mahout.math.VectorView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mahout-math Show documentation
Show all versions of mahout-math Show documentation
High performance scientific and technical computing data structures and methods,
mostly based on CERN's
Colt Java API
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.mahout.math;
import java.util.Iterator;
import com.google.common.collect.AbstractIterator;
/** Implements subset view of a Vector */
public class VectorView extends AbstractVector {
protected Vector vector;
// the offset into the Vector
protected int offset;
/** For serialization purposes only */
public VectorView() {
super(0);
}
public VectorView(Vector vector, int offset, int cardinality) {
super(cardinality);
this.vector = vector;
this.offset = offset;
}
@Override
protected Matrix matrixLike(int rows, int columns) {
return ((AbstractVector) vector).matrixLike(rows, columns);
}
@Override
public Vector clone() {
VectorView r = (VectorView) super.clone();
r.vector = vector.clone();
r.offset = offset;
return r;
}
@Override
public boolean isDense() {
return vector.isDense();
}
@Override
public boolean isSequentialAccess() {
return vector.isSequentialAccess();
}
@Override
public VectorView like() {
return new VectorView(vector.like(), offset, size());
}
@Override
public Vector like(int cardinality) {
return vector.like(cardinality);
}
@Override
public double getQuick(int index) {
return vector.getQuick(offset + index);
}
@Override
public void setQuick(int index, double value) {
vector.setQuick(offset + index, value);
}
@Override
public int getNumNondefaultElements() {
return size();
}
@Override
public Vector viewPart(int offset, int length) {
if (offset < 0) {
throw new IndexException(offset, size());
}
if (offset + length > size()) {
throw new IndexException(offset + length, size());
}
return new VectorView(vector, offset + this.offset, length);
}
/** @return true if index is a valid index in the underlying Vector */
private boolean isInView(int index) {
return index >= offset && index < offset + size();
}
@Override
public Iterator iterateNonZero() {
return new NonZeroIterator();
}
@Override
public Iterator iterator() {
return new AllIterator();
}
public final class NonZeroIterator extends AbstractIterator {
private final Iterator it;
private NonZeroIterator() {
it = vector.nonZeroes().iterator();
}
@Override
protected Element computeNext() {
while (it.hasNext()) {
Element el = it.next();
if (isInView(el.index()) && el.get() != 0) {
Element decorated = el; /* vector.getElement(el.index()); */
return new DecoratorElement(decorated);
}
}
return endOfData();
}
}
public final class AllIterator extends AbstractIterator {
private final Iterator it;
private AllIterator() {
it = vector.all().iterator();
}
@Override
protected Element computeNext() {
while (it.hasNext()) {
Element el = it.next();
if (isInView(el.index())) {
Element decorated = vector.getElement(el.index());
return new DecoratorElement(decorated);
}
}
return endOfData(); // No element was found
}
}
private final class DecoratorElement implements Element {
private final Element decorated;
private DecoratorElement(Element decorated) {
this.decorated = decorated;
}
@Override
public double get() {
return decorated.get();
}
@Override
public int index() {
return decorated.index() - offset;
}
@Override
public void set(double value) {
decorated.set(value);
}
}
@Override
public double getLengthSquared() {
double result = 0.0;
int size = size();
for (int i = 0; i < size; i++) {
double value = getQuick(i);
result += value * value;
}
return result;
}
@Override
public double getDistanceSquared(Vector v) {
double result = 0.0;
int size = size();
for (int i = 0; i < size; i++) {
double delta = getQuick(i) - v.getQuick(i);
result += delta * delta;
}
return result;
}
@Override
public double getLookupCost() {
return vector.getLookupCost();
}
@Override
public double getIteratorAdvanceCost() {
// TODO: remove the 2x after fixing the Element iterator
return 2 * vector.getIteratorAdvanceCost();
}
@Override
public boolean isAddConstantTime() {
return vector.isAddConstantTime();
}
/**
* Used internally by assign() to update multiple indices and values at once.
* Only really useful for sparse vectors (especially SequentialAccessSparseVector).
*
* If someone ever adds a new type of sparse vectors, this method must merge (index, value) pairs into the vector.
*
* @param updates a mapping of indices to values to merge in the vector.
*/
@Override
public void mergeUpdates(OrderedIntDoubleMapping updates) {
for (int i = 0; i < updates.getNumMappings(); ++i) {
updates.setIndexAt(i, updates.indexAt(i) + offset);
}
vector.mergeUpdates(updates);
}
}