/*
* 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.ignite.ml.math.impls.vector;
import org.apache.ignite.ml.math.Matrix;
import org.apache.ignite.ml.math.Vector;
import org.apache.ignite.ml.math.VectorStorage;
import org.apache.ignite.ml.math.functions.IgniteBiFunction;
import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
import org.apache.ignite.ml.math.impls.matrix.FunctionMatrix;
/**
* This class provides a helper implementation of the read-only implementation of {@link Vector}
* interface to minimize the effort required to implement it.
* Subclasses may override some of the implemented methods if a more
* specific or optimized implementation is desirable.
*/
public abstract class AbstractReadOnlyVector extends AbstractVector {
/** */
public AbstractReadOnlyVector() {
// No-op.
}
/**
* @param sto Storage.
*/
public AbstractReadOnlyVector(VectorStorage sto) {
super(true, sto);
}
/** {@inheritDoc} */
@Override public Matrix cross(Vector vec) {
return new FunctionMatrix(size(), vec.size(),
(row, col) -> vec.get(col) * get(row));
}
/** {@inheritDoc} */
@Override public Matrix toMatrix(boolean rowLike) {
return new FunctionMatrix(rowLike ? 1 : size(), rowLike ? size() : 1,
(row, col) -> rowLike ? get(col) : get(row));
}
/** {@inheritDoc} */
@Override public Matrix toMatrixPlusOne(boolean rowLike, double zeroVal) {
return new FunctionMatrix(rowLike ? 1 : size() + 1, rowLike ? size() + 1 : 1, (row, col) -> {
if (row == 0 && col == 0)
return zeroVal;
return rowLike ? get(col - 1) : get(row - 1);
});
}
/** {@inheritDoc} */
@Override public Vector copy() {
return this; // This exploits read-only feature of this type vector.
}
/** {@inheritDoc} */
@Override public Vector logNormalize() {
return logNormalize(2.0, Math.sqrt(getLengthSquared()));
}
/** {@inheritDoc} */
@Override public Vector logNormalize(double power) {
return logNormalize(power, kNorm(power));
}
/** {@inheritDoc} */
@Override public Vector map(IgniteDoubleFunction<Double> fun) {
return new FunctionVector(size(), (i) -> fun.apply(get(i)));
}
/** {@inheritDoc} */
@Override public Vector map(Vector vec, IgniteBiFunction<Double, Double, Double> fun) {
checkCardinality(vec);
return new FunctionVector(size(), (i) -> fun.apply(get(i), vec.get(i)));
}
/** {@inheritDoc} */
@Override public Vector map(IgniteBiFunction<Double, Double, Double> fun, double y) {
return new FunctionVector(size(), (i) -> fun.apply(get(i), y));
}
/** {@inheritDoc} */
@Override public Vector divide(double x) {
if (x == 1.0)
return this;
return new FunctionVector(size(), (i) -> get(i) / x);
}
/** {@inheritDoc} */
@Override public Vector times(double x) {
return x == 0 ? new ConstantVector(size(), 0) : new FunctionVector(size(), (i) -> get(i) * x);
}
/**
* @param power Power.
* @param normLen Normalized length.
* @return logNormalized value.
*/
private Vector logNormalize(double power, double normLen) {
assert !(Double.isInfinite(power) || power <= 1.0);
double denominator = normLen * Math.log(power);
return new FunctionVector(size(), (idx) -> Math.log1p(get(idx)) / denominator);
}
}