/**
* 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 {
private Vector vector;
// the offset into the Vector
private 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 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<Element> iterateNonZero() {
return new NonZeroIterator();
}
@Override
public Iterator<Element> iterator() {
return new AllIterator();
}
public final class NonZeroIterator extends AbstractIterator<Element> {
private final Iterator<Element> it;
private NonZeroIterator() {
it = vector.iterateNonZero();
}
@Override
protected Element computeNext() {
while (it.hasNext()) {
Element el = it.next();
if (isInView(el.index()) && el.get() != 0) {
Element decorated = vector.getElement(el.index());
return new DecoratorElement(decorated);
}
}
return endOfData();
}
}
public final class AllIterator extends AbstractIterator<Element> {
private final Iterator<Element> it;
private AllIterator() {
it = vector.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;
}
}