/* * 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): Maxim Samoylov * Miron Aseev * */ package org.la4j; import java.math.BigDecimal; import java.math.RoundingMode; import org.la4j.vector.VectorFactory; import org.la4j.vector.dense.BasicVector; import org.la4j.vector.functor.VectorAccumulator; import org.la4j.vector.functor.VectorFunction; import org.la4j.vector.functor.VectorPredicate; import org.la4j.vector.functor.VectorProcedure; import org.la4j.vector.sparse.CompressedVector; public final class Vectors { public static final double EPS = LinearAlgebra.EPS; public static final int ROUND_FACTOR = LinearAlgebra.ROUND_FACTOR; public static final VectorFactory<BasicVector> BASIC = new VectorFactory<BasicVector>() { @Override public BasicVector apply(int length) { return BasicVector.zero(length); } }; public static final VectorFactory<CompressedVector> COMPRESSED = new VectorFactory<CompressedVector>() { @Override public CompressedVector apply(int length) { return CompressedVector.zero(length); } }; public static final VectorFactory<?>[] FACTORIES = { BASIC, COMPRESSED }; public static final VectorFactory<BasicVector> DENSE = BASIC; public static final VectorFactory<CompressedVector> SPARSE = COMPRESSED; /** * Checks whether the vector is a * <a href="http://mathworld.wolfram.com/ZeroMatrix.html">zero * vector</a>. */ public static final VectorPredicate ZERO_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return Math.abs(value) < EPS; } }; /** * Checks whether the vector is a * <a href="http://mathworld.wolfram.com/PositiveMatrix.html">positive * vector</a>. */ public static final VectorPredicate POSITIVE_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return value > 0.0; } }; /** * Checks whether the vector is a * <a href="http://mathworld.wolfram.com/NegativeMatrix.html">negative * vector</a>. */ public static final VectorPredicate NEGATIVE_VECTOR = new VectorPredicate() { @Override public boolean test(int i, double value) { return value < 0.0; } }; /** * Increases each element of vector by <code>1</code>. */ public static final VectorFunction INC_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return value + 1.0; } }; /** * Decreases each element of vectors by <code>1</code>. */ public static final VectorFunction DEC_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return value - 1.0; } }; /** * Inverts each element of vector. */ public static final VectorFunction INV_FUNCTION = new VectorFunction() { @Override public double evaluate(int i, double value) { return -value; } }; private Vectors() {} /** * Creates a const function that evaluates it's argument to given {@code value}. * * @param arg a const value * * @return a closure object that does {@code _} */ public static VectorFunction asConstFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return arg; } }; } /** * Creates a plus function that adds given {@code value} to it's argument. * * @param arg a value to be added to function's argument * * @return a closure object that does {@code _ + _} */ public static VectorFunction asPlusFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value + arg; } }; } /** * Creates a minus function that subtracts given {@code value} from it's argument. * * @param arg a value to be subtracted from function's argument * * @return a closure that does {@code _ - _} */ public static VectorFunction asMinusFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value - arg; } }; } /** * Creates a mul function that multiplies given {@code value} by it's argument. * * @param arg a value to be multiplied by function's argument * * @return a closure that does {@code _ * _} */ public static VectorFunction asMulFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value * arg; } }; } /** * Creates a div function that divides it's argument by given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ / _} */ public static VectorFunction asDivFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value / arg; } }; } /** * Creates a mod function that calculates the modulus of it's argument and given {@code value}. * * @param arg a divisor value * * @return a closure that does {@code _ % _} */ public static VectorFunction asModFunction(final double arg) { return new VectorFunction() { @Override public double evaluate(int i, double value) { return value % arg; } }; } /** * Creates a sum vector accumulator that calculates the sum of all elements in the vector. * * @param neutral the neutral value * * @return a sum accumulator */ public static VectorAccumulator asSumAccumulator(final double neutral) { return new VectorAccumulator() { private BigDecimal result = BigDecimal.valueOf(neutral); @Override public void update(int i, double value) { result = result.add(BigDecimal.valueOf(value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = BigDecimal.valueOf(neutral); return value; } }; } /** * Creates a product vector accumulator that calculates the product of all elements in the vector. * * @param neutral the neutral value * * @return a product accumulator */ public static VectorAccumulator asProductAccumulator(final double neutral) { return new VectorAccumulator() { private BigDecimal result = BigDecimal.valueOf(neutral); @Override public void update(int i, double value) { result = result.multiply(BigDecimal.valueOf(value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = BigDecimal.valueOf(neutral); return value; } }; } /** * Makes a minimum vector accumulator that accumulates the minimum across vector elements. * * @return a minimum vector accumulator */ public static VectorAccumulator mkMinAccumulator() { return new VectorAccumulator() { private double result = Double.POSITIVE_INFINITY; @Override public void update(int i, double value) { result = Math.min(result, value); } @Override public double accumulate() { double value = result; result = Double.POSITIVE_INFINITY; return value; } }; } /** * Makes a maximum vector accumulator that accumulates the maximum across vector elements. * * @return a maximum vector accumulator */ public static VectorAccumulator mkMaxAccumulator() { return new VectorAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, double value) { result = Math.max(result, value); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Makes an Euclidean norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return an Euclidean norm accumulator */ public static VectorAccumulator mkEuclideanNormAccumulator() { return new VectorAccumulator() { private BigDecimal result = BigDecimal.valueOf(0.0); @Override public void update(int i, double value) { result = result.add(BigDecimal.valueOf(value * value)); } @Override public double accumulate() { double value = result.setScale(Vectors.ROUND_FACTOR, RoundingMode.CEILING).doubleValue(); result = BigDecimal.valueOf(0.0); return Math.sqrt(value); } }; } /** * Makes a Manhattan norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return a Manhattan norm accumulator */ public static VectorAccumulator mkManhattanNormAccumulator() { return new VectorAccumulator() { private double result = 0.0; @Override public void update(int i, double value) { result += Math.abs(value); } @Override public double accumulate() { double value = result; result = 0.0; return value; } }; } /** * Makes an Infinity norm accumulator that allows to use * {@link org.la4j.Vector#fold(org.la4j.vector.functor.VectorAccumulator)} method for norm calculation. * * @return an Infinity norm accumulator */ public static VectorAccumulator mkInfinityNormAccumulator() { return new VectorAccumulator() { private double result = Double.NEGATIVE_INFINITY; @Override public void update(int i, double value) { result = Math.max(result, Math.abs(value)); } @Override public double accumulate() { double value = result; result = Double.NEGATIVE_INFINITY; return value; } }; } /** * Creates a sum function accumulator, that calculates the sum of all * elements in the vector after applying given {@code function} to each of them. * * @param neutral the neutral value * @param function the vector function * * @return a sum function accumulator */ public static VectorAccumulator asSumFunctionAccumulator(final double neutral, final VectorFunction function) { return new VectorAccumulator() { private final VectorAccumulator sumAccumulator = Vectors.asSumAccumulator(neutral); @Override public void update(int i, double value) { sumAccumulator.update(i, function.evaluate(i, value)); } @Override public double accumulate() { return sumAccumulator.accumulate(); } }; } /** * Creates a product function accumulator, that calculates the product of * all elements in the vector after applying given {@code function} to * each of them. * * @param neutral the neutral value * @param function the vector function * * @return a product function accumulator */ public static VectorAccumulator asProductFunctionAccumulator(final double neutral, final VectorFunction function) { return new VectorAccumulator() { private final VectorAccumulator productAccumulator = Vectors.asProductAccumulator(neutral); @Override public void update(int i, double value) { productAccumulator.update(i, function.evaluate(i, value)); } @Override public double accumulate() { return productAccumulator.accumulate(); } }; } /** * Creates an accumulator procedure that adapts a vector accumulator for procedure * interface. This is useful for reusing a single accumulator for multiple fold operations * in multiple vectors. * * @param accumulator the vector accumulator * * @return an accumulator procedure */ public static VectorProcedure asAccumulatorProcedure(final VectorAccumulator accumulator) { return new VectorProcedure() { @Override public void apply(int i, double value) { accumulator.update(i, value); } }; } }