| /* |
| * 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.commons.math4.linear; |
| |
| import java.io.Serializable; |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| |
| import org.apache.commons.math4.TestUtils; |
| import org.apache.commons.math4.analysis.UnivariateFunction; |
| import org.apache.commons.math4.analysis.function.Abs; |
| import org.apache.commons.math4.analysis.function.Acos; |
| import org.apache.commons.math4.analysis.function.Asin; |
| import org.apache.commons.math4.analysis.function.Atan; |
| import org.apache.commons.math4.analysis.function.Cbrt; |
| import org.apache.commons.math4.analysis.function.Ceil; |
| import org.apache.commons.math4.analysis.function.Cos; |
| import org.apache.commons.math4.analysis.function.Cosh; |
| import org.apache.commons.math4.analysis.function.Exp; |
| import org.apache.commons.math4.analysis.function.Expm1; |
| import org.apache.commons.math4.analysis.function.Floor; |
| import org.apache.commons.math4.analysis.function.Inverse; |
| import org.apache.commons.math4.analysis.function.Log; |
| import org.apache.commons.math4.analysis.function.Log10; |
| import org.apache.commons.math4.analysis.function.Log1p; |
| import org.apache.commons.math4.analysis.function.Power; |
| import org.apache.commons.math4.analysis.function.Rint; |
| import org.apache.commons.math4.analysis.function.Signum; |
| import org.apache.commons.math4.analysis.function.Sin; |
| import org.apache.commons.math4.analysis.function.Sinh; |
| import org.apache.commons.math4.analysis.function.Sqrt; |
| import org.apache.commons.math4.analysis.function.Tan; |
| import org.apache.commons.math4.analysis.function.Tanh; |
| import org.apache.commons.math4.analysis.function.Ulp; |
| import org.apache.commons.math4.exception.DimensionMismatchException; |
| import org.apache.commons.math4.exception.MathArithmeticException; |
| import org.apache.commons.math4.exception.MathUnsupportedOperationException; |
| import org.apache.commons.math4.exception.NotPositiveException; |
| import org.apache.commons.math4.exception.NumberIsTooSmallException; |
| import org.apache.commons.math4.exception.OutOfRangeException; |
| import org.apache.commons.math4.linear.OpenMapRealVector; |
| import org.apache.commons.math4.linear.RealMatrix; |
| import org.apache.commons.math4.linear.RealVector; |
| import org.apache.commons.math4.linear.RealVectorChangingVisitor; |
| import org.apache.commons.math4.linear.RealVectorPreservingVisitor; |
| import org.apache.commons.math4.util.FastMath; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| |
| public abstract class RealVectorAbstractTest { |
| |
| protected enum BinaryOperation { |
| ADD, SUB, MUL, DIV |
| } |
| |
| /** |
| * <p> |
| * This is an attempt at covering most particular cases of combining two |
| * values. Here {@code x} is the value returned by |
| * {@link #getPreferredEntryValue()}, while {@code y} and {@code z} are two |
| * "normal" values. |
| * </p> |
| * <ol> |
| * <li> |
| * Addition: the following cases should be covered |
| * <ul> |
| * <li>{@code (2 * x) + (-x)}</li> |
| * <li>{@code (-x) + 2 * x}</li> |
| * <li>{@code x + y}</li> |
| * <li>{@code y + x}</li> |
| * <li>{@code y + z}</li> |
| * <li>{@code y + (x - y)}</li> |
| * <li>{@code (y - x) + x}</li> |
| * </ul> |
| * The values to be considered are: |
| * {@code x, y, z, 2 * x, -x, x - y, y - x}. |
| * </li> |
| * <li> |
| * Subtraction: the following cases should be covered |
| * <ul> |
| * <li>{@code (2 * x) - x}</li> |
| * <li>{@code x - y}</li> |
| * <li>{@code y - x}</li> |
| * <li>{@code y - z}</li> |
| * <li>{@code y - (y - x)}</li> |
| * <li>{@code (y + x) - y}</li> |
| * </ul> |
| * The values to be considered are: {@code x, y, z, x + y, y - x}. |
| * </li> |
| * <li> |
| * Multiplication |
| * <ul> |
| * <li>{@code (x * x) * (1 / x)}</li> |
| * <li>{@code (1 / x) * (x * x)}</li> |
| * <li>{@code x * y}</li> |
| * <li>{@code y * x}</li> |
| * <li>{@code y * z}</li> |
| * </ul> |
| * The values to be considered are: {@code x, y, z, 1 / x, x * x}. |
| * </li> |
| * <li> |
| * Division |
| * <ul> |
| * <li>{@code (x * x) / x}</li> |
| * <li>{@code x / y}</li> |
| * <li>{@code y / x}</li> |
| * <li>{@code y / z}</li> |
| * </ul> |
| * The values to be considered are: {@code x, y, z, x * x}. |
| * </li> |
| * </ol> |
| * Also to be considered {@code NaN}, {@code POSITIVE_INFINITY}, |
| * {@code NEGATIVE_INFINITY}, {@code +0.0}, {@code -0.0}. |
| */ |
| private final double[] values; |
| |
| /** |
| * Creates a new instance of {@link RealVector}, with specified entries. |
| * The returned vector must be of the type currently tested. It should be |
| * noted that some tests assume that no references to the specified |
| * {@code double[]} are kept in the returned object: if necessary, defensive |
| * copy of this array should be made. |
| * |
| * @param data the entries of the vector to be created |
| * @return a new {@link RealVector} of the type to be tested |
| */ |
| public abstract RealVector create(double[] data); |
| |
| /** |
| * Creates a new instance of {@link RealVector}, with specified entries. |
| * The type of the returned vector must be different from the type currently |
| * tested. It should be noted that some tests assume that no references to |
| * the specified {@code double[]} are kept in the returned object: if |
| * necessary, defensive copy of this array should be made. |
| * |
| * @param data the entries of the vector to be created |
| * @return a new {@link RealVector} of an alien type |
| */ |
| public RealVector createAlien(double[] data){ |
| return new RealVectorTestImpl(data); |
| } |
| |
| /** |
| * Returns a preferred value of the entries, to be tested specifically. Some |
| * implementations of {@link RealVector} (e.g. {@link OpenMapRealVector}) do |
| * not store specific values of entries. In order to ensure that all tests |
| * take into account this specific value, some entries of the vectors to be |
| * tested are deliberately set to the value returned by the present method. |
| * The default implementation returns {@code 0.0}. |
| * |
| * @return a value which <em>should</em> be present in all vectors to be |
| * tested |
| */ |
| public double getPreferredEntryValue() { |
| return 0.0; |
| } |
| |
| public RealVectorAbstractTest() { |
| /* |
| * Make sure that x, y, z are three different values. Also, x is the |
| * preferred value (e.g. the value which is not stored in sparse |
| * implementations). |
| */ |
| final double x = getPreferredEntryValue(); |
| final double y = x + 1d; |
| final double z = y + 1d; |
| |
| values = |
| new double[] { |
| Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, |
| 0d, -0d, x, y, z, 2 * x, -x, 1 / x, x * x, x + y, x - y, y - x |
| }; |
| } |
| |
| @Test |
| public void testGetDimension() { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = {x, x, x, x}; |
| Assert.assertEquals(data1.length, create(data1).getDimension()); |
| final double y = x + 1; |
| final double[] data2 = {y, y, y, y}; |
| Assert.assertEquals(data2.length, create(data2).getDimension()); |
| } |
| |
| @Test |
| public void testGetEntry() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = {x, 1d, 2d, x, x}; |
| final RealVector v = create(data); |
| for (int i = 0; i < data.length; i++) { |
| Assert.assertEquals("entry " + i, data[i], v.getEntry(i), 0d); |
| } |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testGetEntryInvalidIndex1() { |
| create(new double[4]).getEntry(-1); |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testGetEntryInvalidIndex2() { |
| create(new double[4]).getEntry(4); |
| } |
| |
| @Test |
| public void testSetEntry() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = {x, 1d, 2d, x, x}; |
| final double[] expected = Arrays.copyOf(data, data.length); |
| final RealVector actual = create(data); |
| |
| /* |
| * Try setting to any value. |
| */ |
| for (int i = 0; i < data.length; i++) { |
| final double oldValue = data[i]; |
| final double newValue = oldValue + 1d; |
| expected[i] = newValue; |
| actual.setEntry(i, newValue); |
| TestUtils.assertEquals("while setting entry #" + i, expected, |
| actual, 0d); |
| expected[i] = oldValue; |
| actual.setEntry(i, oldValue); |
| } |
| |
| /* |
| * Try setting to the preferred value. |
| */ |
| for (int i = 0; i < data.length; i++) { |
| final double oldValue = data[i]; |
| final double newValue = x; |
| expected[i] = newValue; |
| actual.setEntry(i, newValue); |
| TestUtils.assertEquals("while setting entry #" + i, expected, |
| actual, 0d); |
| expected[i] = oldValue; |
| actual.setEntry(i, oldValue); |
| } |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testSetEntryInvalidIndex1() { |
| create(new double[4]).setEntry(-1, getPreferredEntryValue()); |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testSetEntryInvalidIndex2() { |
| create(new double[4]).setEntry(4, getPreferredEntryValue()); |
| } |
| |
| @Test |
| public void testAddToEntry() { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = {x, 1d, 2d, x, x}; |
| |
| final double[] expected = Arrays.copyOf(data1, data1.length); |
| final RealVector actual = create(data1); |
| |
| /* |
| * Try adding any value. |
| */ |
| double increment = 1d; |
| for (int i = 0; i < data1.length; i++) { |
| final double oldValue = data1[i]; |
| expected[i] += increment; |
| actual.addToEntry(i, increment); |
| TestUtils.assertEquals("while incrementing entry #" + i, expected, |
| actual, 0d); |
| expected[i] = oldValue; |
| actual.setEntry(i, oldValue); |
| } |
| |
| /* |
| * Try incrementing so that result is equal to preferred value. |
| */ |
| for (int i = 0; i < data1.length; i++) { |
| final double oldValue = data1[i]; |
| increment = x - oldValue; |
| expected[i] = x; |
| actual.addToEntry(i, increment); |
| TestUtils.assertEquals("while incrementing entry #" + i, expected, |
| actual, 0d); |
| expected[i] = oldValue; |
| actual.setEntry(i, oldValue); |
| } |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testAddToEntryInvalidIndex1() { |
| create(new double[3]).addToEntry(-1, getPreferredEntryValue()); |
| } |
| |
| @Test(expected=OutOfRangeException.class) |
| public void testAddToEntryInvalidIndex2() { |
| create(new double[3]).addToEntry(4, getPreferredEntryValue()); |
| } |
| |
| private void doTestAppendVector(final String message, final RealVector v1, |
| final RealVector v2, final double delta) { |
| |
| final int n1 = v1.getDimension(); |
| final int n2 = v2.getDimension(); |
| final RealVector v = v1.append(v2); |
| Assert.assertEquals(message, n1 + n2, v.getDimension()); |
| for (int i = 0; i < n1; i++) { |
| final String msg = message + ", entry #" + i; |
| Assert.assertEquals(msg, v1.getEntry(i), v.getEntry(i), delta); |
| } |
| for (int i = 0; i < n2; i++) { |
| final String msg = message + ", entry #" + (n1 + i); |
| Assert.assertEquals(msg, v2.getEntry(i), v.getEntry(n1 + i), delta); |
| } |
| } |
| |
| @Test |
| public void testAppendVector() { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = {x, 1d, 2d, x, x}; |
| final double[] data2 = {x, x, 3d, x, 4d, x}; |
| |
| doTestAppendVector("same type", create(data1), create(data2), 0d); |
| doTestAppendVector("mixed types", create(data1), createAlien(data2), 0d); |
| } |
| |
| private void doTestAppendScalar(final String message, final RealVector v, |
| final double d, final double delta) { |
| |
| final int n = v.getDimension(); |
| final RealVector w = v.append(d); |
| Assert.assertEquals(message, n + 1, w.getDimension()); |
| for (int i = 0; i < n; i++) { |
| final String msg = message + ", entry #" + i; |
| Assert.assertEquals(msg, v.getEntry(i), w.getEntry(i), delta); |
| } |
| final String msg = message + ", entry #" + n; |
| Assert.assertEquals(msg, d, w.getEntry(n), delta); |
| } |
| |
| @Test |
| public void testAppendScalar() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = new double[] {x, 1d, 2d, x, x}; |
| |
| doTestAppendScalar("", create(data), 1d, 0d); |
| doTestAppendScalar("", create(data), x, 0d); |
| } |
| |
| @Test |
| public void testGetSubVector() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x}; |
| final int index = 1; |
| final int n = data.length - 5; |
| final RealVector actual = create(data).getSubVector(index, n); |
| final double[] expected = new double[n]; |
| System.arraycopy(data, index, expected, 0, n); |
| TestUtils.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testGetSubVectorInvalidIndex1() { |
| final int n = 10; |
| create(new double[n]).getSubVector(-1, 2); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testGetSubVectorInvalidIndex2() { |
| final int n = 10; |
| create(new double[n]).getSubVector(n, 2); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testGetSubVectorInvalidIndex3() { |
| final int n = 10; |
| create(new double[n]).getSubVector(0, n + 1); |
| } |
| |
| @Test(expected = NotPositiveException.class) |
| public void testGetSubVectorInvalidIndex4() { |
| final int n = 10; |
| create(new double[n]).getSubVector(3, -2); |
| } |
| |
| @Test |
| public void testSetSubVectorSameType() { |
| final double x = getPreferredEntryValue(); |
| final double[] expected = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x}; |
| final double[] sub = {5d, x, 6d, 7d, 8d}; |
| final RealVector actual = create(expected); |
| final int index = 2; |
| actual.setSubVector(index, create(sub)); |
| |
| for (int i = 0; i < sub.length; i++){ |
| expected[index + i] = sub[i]; |
| } |
| TestUtils.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testSetSubVectorMixedType() { |
| final double x = getPreferredEntryValue(); |
| final double[] expected = {x, x, x, 1d, x, 2d, x, x, 3d, x, x, x, 4d, x, x, x}; |
| final double[] sub = {5d, x, 6d, 7d, 8d}; |
| final RealVector actual = create(expected); |
| final int index = 2; |
| actual.setSubVector(index, createAlien(sub)); |
| |
| for (int i = 0; i < sub.length; i++){ |
| expected[index + i] = sub[i]; |
| } |
| TestUtils.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testSetSubVectorInvalidIndex1() { |
| create(new double[10]).setSubVector(-1, create(new double[2])); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testSetSubVectorInvalidIndex2() { |
| create(new double[10]).setSubVector(10, create(new double[2])); |
| } |
| |
| @Test(expected = OutOfRangeException.class) |
| public void testSetSubVectorInvalidIndex3() { |
| create(new double[10]).setSubVector(9, create(new double[2])); |
| } |
| |
| @Test |
| public void testIsNaN() { |
| final RealVector v = create(new double[] {0, 1, 2}); |
| |
| Assert.assertFalse(v.isNaN()); |
| v.setEntry(1, Double.NaN); |
| Assert.assertTrue(v.isNaN()); |
| } |
| |
| @Test |
| public void testIsInfinite() { |
| final RealVector v = create(new double[] { 0, 1, 2 }); |
| |
| Assert.assertFalse(v.isInfinite()); |
| v.setEntry(0, Double.POSITIVE_INFINITY); |
| Assert.assertTrue(v.isInfinite()); |
| v.setEntry(1, Double.NaN); |
| Assert.assertFalse(v.isInfinite()); |
| } |
| |
| protected void doTestEbeBinaryOperation(final BinaryOperation op, final boolean mixed, boolean ignoreSpecial) { |
| final double[] data1 = new double[values.length * values.length]; |
| final double[] data2 = new double[values.length * values.length]; |
| int k = 0; |
| for (int i = 0; i < values.length; i++) { |
| for (int j = 0; j < values.length; j++) { |
| data1[k] = values[i]; |
| data2[k] = values[j]; |
| ++k; |
| } |
| } |
| final RealVector v1 = create(data1); |
| final RealVector v2 = mixed ? createAlien(data2) : create(data2); |
| final RealVector actual; |
| switch (op) { |
| case ADD: |
| actual = v1.add(v2); |
| break; |
| case SUB: |
| actual = v1.subtract(v2); |
| break; |
| case MUL: |
| actual = v1.ebeMultiply(v2); |
| break; |
| case DIV: |
| actual = v1.ebeDivide(v2); |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| final double[] expected = new double[data1.length]; |
| for (int i = 0; i < expected.length; i++) { |
| switch (op) { |
| case ADD: |
| expected[i] = data1[i] + data2[i]; |
| break; |
| case SUB: |
| expected[i] = data1[i] - data2[i]; |
| break; |
| case MUL: |
| expected[i] = data1[i] * data2[i]; |
| break; |
| case DIV: |
| expected[i] = data1[i] / data2[i]; |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| } |
| for (int i = 0; i < expected.length; i++) { |
| boolean isSpecial = Double.isNaN(expected[i]) || Double.isInfinite(expected[i]); |
| if (!(isSpecial && ignoreSpecial)) { |
| final String msg = "entry #"+i+", left = "+data1[i]+", right = " + data2[i]; |
| Assert.assertEquals(msg, expected[i], actual.getEntry(i), 0.0); |
| } |
| } |
| } |
| |
| private void doTestEbeBinaryOperationDimensionMismatch(final BinaryOperation op) { |
| final int n = 10; |
| switch (op) { |
| case ADD: |
| create(new double[n]).add(create(new double[n + 1])); |
| break; |
| case SUB: |
| create(new double[n]).subtract(create(new double[n + 1])); |
| break; |
| case MUL: |
| create(new double[n]).ebeMultiply(create(new double[n + 1])); |
| break; |
| case DIV: |
| create(new double[n]).ebeDivide(create(new double[n + 1])); |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| } |
| |
| @Test |
| public void testAddSameType() { |
| doTestEbeBinaryOperation(BinaryOperation.ADD, false, false); |
| } |
| |
| @Test |
| public void testAddMixedTypes() { |
| doTestEbeBinaryOperation(BinaryOperation.ADD, true, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testAddDimensionMismatch() { |
| doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.ADD); |
| } |
| |
| @Test |
| public void testSubtractSameType() { |
| doTestEbeBinaryOperation(BinaryOperation.SUB, false, false); |
| } |
| |
| @Test |
| public void testSubtractMixedTypes() { |
| doTestEbeBinaryOperation(BinaryOperation.SUB, true, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testSubtractDimensionMismatch() { |
| doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.SUB); |
| } |
| |
| @Test |
| public void testEbeMultiplySameType() { |
| doTestEbeBinaryOperation(BinaryOperation.MUL, false, false); |
| } |
| |
| @Test |
| public void testEbeMultiplyMixedTypes() { |
| doTestEbeBinaryOperation(BinaryOperation.MUL, true, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testEbeMultiplyDimensionMismatch() { |
| doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.MUL); |
| } |
| |
| @Test |
| public void testEbeDivideSameType() { |
| doTestEbeBinaryOperation(BinaryOperation.DIV, false, false); |
| } |
| |
| @Test |
| public void testEbeDivideMixedTypes() { |
| doTestEbeBinaryOperation(BinaryOperation.DIV, true, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testEbeDivideDimensionMismatch() { |
| doTestEbeBinaryOperationDimensionMismatch(BinaryOperation.DIV); |
| } |
| |
| private void doTestGetDistance(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d }; |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double actual = v1.getDistance(v2); |
| double expected = 0d; |
| for (int i = 0; i < data1.length; i++) { |
| final double delta = data2[i] - data1[i]; |
| expected += delta * delta; |
| } |
| expected = FastMath.sqrt(expected); |
| Assert.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testGetDistanceSameType() { |
| doTestGetDistance(false); |
| } |
| |
| @Test |
| public void testGetDistanceMixedTypes() { |
| doTestGetDistance(true); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testGetDistanceDimensionMismatch() { |
| create(new double[4]).getDistance(createAlien(new double[5])); |
| } |
| |
| @Test |
| public void testGetNorm() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final RealVector v = create(data); |
| final double actual = v.getNorm(); |
| double expected = 0d; |
| for (int i = 0; i < data.length; i++) { |
| expected += data[i] * data[i]; |
| } |
| expected = FastMath.sqrt(expected); |
| Assert.assertEquals("", expected, actual, 0d); |
| } |
| |
| private void doTestGetL1Distance(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d }; |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double actual = v1.getL1Distance(v2); |
| double expected = 0d; |
| for (int i = 0; i < data1.length; i++) { |
| final double delta = data2[i] - data1[i]; |
| expected += FastMath.abs(delta); |
| } |
| Assert.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testGetL1DistanceSameType() { |
| doTestGetL1Distance(false); |
| } |
| |
| @Test |
| public void testGetL1DistanceMixedTypes() { |
| doTestGetL1Distance(true); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testGetL1DistanceDimensionMismatch() { |
| create(new double[4]).getL1Distance(createAlien(new double[5])); |
| } |
| |
| @Test |
| public void testGetL1Norm() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final RealVector v = create(data); |
| final double actual = v.getL1Norm(); |
| double expected = 0d; |
| for (int i = 0; i < data.length; i++) { |
| expected += FastMath.abs(data[i]); |
| } |
| Assert.assertEquals("", expected, actual, 0d); |
| |
| } |
| |
| private void doTestGetLInfDistance(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final double[] data2 = new double[] { 4d, x, x, 5d, 6d, 7d, x, x, 8d }; |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double actual = v1.getLInfDistance(v2); |
| double expected = 0d; |
| for (int i = 0; i < data1.length; i++) { |
| final double delta = data2[i] - data1[i]; |
| expected = FastMath.max(expected, FastMath.abs(delta)); |
| } |
| Assert.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testGetLInfDistanceSameType() { |
| doTestGetLInfDistance(false); |
| } |
| |
| @Test |
| public void testGetLInfDistanceMixedTypes() { |
| doTestGetLInfDistance(true); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testGetLInfDistanceDimensionMismatch() { |
| create(new double[4]).getLInfDistance(createAlien(new double[5])); |
| } |
| |
| @Test |
| public void testGetLInfNorm() { |
| final double x = getPreferredEntryValue(); |
| final double[] data = new double[] { x, x, 1d, x, 2d, x, x, 3d, x }; |
| final RealVector v = create(data); |
| final double actual = v.getLInfNorm(); |
| double expected = 0d; |
| for (int i = 0; i < data.length; i++) { |
| expected = FastMath.max(expected, FastMath.abs(data[i])); |
| } |
| Assert.assertEquals("", expected, actual, 0d); |
| |
| } |
| |
| private void doTestMapBinaryOperation(final BinaryOperation op, final boolean inPlace) { |
| final double[] expected = new double[values.length]; |
| for (int i = 0; i < values.length; i++) { |
| final double d = values[i]; |
| for (int j = 0; j < expected.length; j++) { |
| switch (op) { |
| case ADD: |
| expected[j] = values[j] + d; |
| break; |
| case SUB: |
| expected[j] = values[j] - d; |
| break; |
| case MUL: |
| expected[j] = values[j] * d; |
| break; |
| case DIV: |
| expected[j] = values[j] / d; |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| } |
| final RealVector v = create(values); |
| final RealVector actual; |
| if (inPlace) { |
| switch (op) { |
| case ADD: |
| actual = v.mapAddToSelf(d); |
| break; |
| case SUB: |
| actual = v.mapSubtractToSelf(d); |
| break; |
| case MUL: |
| actual = v.mapMultiplyToSelf(d); |
| break; |
| case DIV: |
| actual = v.mapDivideToSelf(d); |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| } else { |
| switch (op) { |
| case ADD: |
| actual = v.mapAdd(d); |
| break; |
| case SUB: |
| actual = v.mapSubtract(d); |
| break; |
| case MUL: |
| actual = v.mapMultiply(d); |
| break; |
| case DIV: |
| actual = v.mapDivide(d); |
| break; |
| default: |
| throw new AssertionError("unexpected value"); |
| } |
| } |
| TestUtils.assertEquals(Double.toString(d), expected, actual, 0d); |
| } |
| } |
| |
| @Test |
| public void testMapAdd() { |
| doTestMapBinaryOperation(BinaryOperation.ADD, false); |
| } |
| |
| @Test |
| public void testMapAddToSelf() { |
| doTestMapBinaryOperation(BinaryOperation.ADD, true); |
| } |
| |
| @Test |
| public void testMapSubtract() { |
| doTestMapBinaryOperation(BinaryOperation.SUB, false); |
| } |
| |
| @Test |
| public void testMapSubtractToSelf() { |
| doTestMapBinaryOperation(BinaryOperation.SUB, true); |
| } |
| |
| @Test |
| public void testMapMultiply() { |
| doTestMapBinaryOperation(BinaryOperation.MUL, false); |
| } |
| |
| @Test |
| public void testMapMultiplyToSelf() { |
| doTestMapBinaryOperation(BinaryOperation.MUL, true); |
| } |
| |
| @Test |
| public void testMapDivide() { |
| doTestMapBinaryOperation(BinaryOperation.DIV, false); |
| } |
| |
| @Test |
| public void testMapDivideToSelf() { |
| doTestMapBinaryOperation(BinaryOperation.DIV, true); |
| } |
| |
| private void doTestMapFunction(final UnivariateFunction f, |
| final boolean inPlace) { |
| final double[] data = new double[values.length + 6]; |
| System.arraycopy(values, 0, data, 0, values.length); |
| data[values.length + 0] = 0.5 * FastMath.PI; |
| data[values.length + 1] = -0.5 * FastMath.PI; |
| data[values.length + 2] = FastMath.E; |
| data[values.length + 3] = -FastMath.E; |
| data[values.length + 4] = 1.0; |
| data[values.length + 5] = -1.0; |
| final double[] expected = new double[data.length]; |
| for (int i = 0; i < data.length; i++) { |
| expected[i] = f.value(data[i]); |
| } |
| final RealVector v = create(data); |
| final RealVector actual; |
| if (inPlace) { |
| actual = v.mapToSelf(f); |
| Assert.assertSame(v, actual); |
| } else { |
| actual = v.map(f); |
| } |
| TestUtils.assertEquals(f.getClass().getSimpleName(), expected, actual, 1E-16); |
| } |
| |
| protected UnivariateFunction[] createFunctions() { |
| return new UnivariateFunction[] { |
| new Power(2.0), new Exp(), new Expm1(), new Log(), new Log10(), |
| new Log1p(), new Cosh(), new Sinh(), new Tanh(), new Cos(), |
| new Sin(), new Tan(), new Acos(), new Asin(), new Atan(), |
| new Inverse(), new Abs(), new Sqrt(), new Cbrt(), new Ceil(), |
| new Floor(), new Rint(), new Signum(), new Ulp() |
| }; |
| } |
| |
| @Test |
| public void testMap() { |
| final UnivariateFunction[] functions = createFunctions(); |
| for (UnivariateFunction f : functions) { |
| doTestMapFunction(f, false); |
| } |
| } |
| |
| @Test |
| public void testMapToSelf() { |
| final UnivariateFunction[] functions = createFunctions(); |
| for (UnivariateFunction f : functions) { |
| doTestMapFunction(f, true); |
| } |
| } |
| |
| private void doTestOuterProduct(final boolean mixed) { |
| final double[] dataU = values; |
| final RealVector u = create(dataU); |
| final double[] dataV = new double[values.length + 3]; |
| System.arraycopy(values, 0, dataV, 0, values.length); |
| dataV[values.length] = 1d; |
| dataV[values.length] = -2d; |
| dataV[values.length] = 3d; |
| final RealVector v; |
| if (mixed) { |
| v = createAlien(dataV); |
| } else { |
| v = create(dataV); |
| } |
| final RealMatrix uv = u.outerProduct(v); |
| Assert.assertEquals("number of rows", dataU.length, uv |
| .getRowDimension()); |
| Assert.assertEquals("number of columns", dataV.length, uv |
| .getColumnDimension()); |
| for (int i = 0; i < dataU.length; i++) { |
| for (int j = 0; j < dataV.length; j++) { |
| final double expected = dataU[i] * dataV[j]; |
| final double actual = uv.getEntry(i, j); |
| Assert.assertEquals(dataU[i] + " * " + dataV[j], expected, actual, 0d); |
| } |
| } |
| } |
| |
| @Test |
| public void testOuterProductSameType() { |
| doTestOuterProduct(false); |
| } |
| |
| @Test |
| public void testOuterProductMixedTypes() { |
| doTestOuterProduct(true); |
| } |
| |
| private void doTestProjection(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = { |
| x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x |
| }; |
| final double[] data2 = { |
| 5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d |
| }; |
| double dotProduct = 0d; |
| double norm2 = 0d; |
| for (int i = 0; i < data1.length; i++){ |
| dotProduct += data1[i] * data2[i]; |
| norm2 += data2[i] * data2[i]; |
| } |
| final double s = dotProduct / norm2; |
| final double[] expected = new double[data1.length]; |
| for (int i = 0; i < data2.length; i++) { |
| expected[i] = s * data2[i]; |
| } |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final RealVector actual = v1.projection(v2); |
| TestUtils.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testProjectionSameType() { |
| doTestProjection(false); |
| } |
| |
| @Test |
| public void testProjectionMixedTypes() { |
| doTestProjection(true); |
| } |
| |
| @Test(expected = MathArithmeticException.class) |
| public void testProjectionNullVector() { |
| create(new double[4]).projection(create(new double[4])); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testProjectionDimensionMismatch() { |
| final RealVector v1 = create(new double[4]); |
| final RealVector v2 = create(new double[5]); |
| v2.set(1.0); |
| v1.projection(v2); |
| } |
| |
| @Test |
| public void testSet() { |
| for (int i = 0; i < values.length; i++) { |
| final double expected = values[i]; |
| final RealVector v = create(values); |
| v.set(expected); |
| for (int j = 0; j < values.length; j++) { |
| Assert.assertEquals("entry #" + j, expected, v.getEntry(j), 0); |
| } |
| } |
| } |
| |
| @Test |
| public void testToArray() { |
| final double[] data = create(values).toArray(); |
| Assert.assertNotSame(values, data); |
| for (int i = 0; i < values.length; i++) { |
| Assert.assertEquals("entry #" + i, values[i], data[i], 0); |
| } |
| } |
| |
| private void doTestUnitVector(final boolean inPlace) { |
| final double x = getPreferredEntryValue(); |
| final double[] data = { |
| x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x |
| }; |
| double norm = 0d; |
| for (int i = 0; i < data.length; i++) { |
| norm += data[i] * data[i]; |
| } |
| norm = FastMath.sqrt(norm); |
| final double[] expected = new double[data.length]; |
| for (int i = 0; i < expected.length; i++) { |
| expected[i] = data[i] / norm; |
| } |
| final RealVector v = create(data); |
| final RealVector actual; |
| if (inPlace) { |
| v.unitize(); |
| actual = v; |
| } else { |
| actual = v.unitVector(); |
| Assert.assertNotSame(v, actual); |
| } |
| TestUtils.assertEquals("", expected, actual, 0d); |
| } |
| |
| @Test |
| public void testUnitVector() { |
| doTestUnitVector(false); |
| } |
| |
| @Test |
| public void testUnitize() { |
| doTestUnitVector(true); |
| } |
| |
| private void doTestUnitVectorNullVector(final boolean inPlace) { |
| final double[] data = { |
| 0d, 0d, 0d, 0d, 0d |
| }; |
| if (inPlace) { |
| create(data).unitize(); |
| } else { |
| create(data).unitVector(); |
| } |
| } |
| |
| @Test(expected=MathArithmeticException.class) |
| public void testUnitVectorNullVector() { |
| doTestUnitVectorNullVector(false); |
| } |
| |
| @Test(expected=MathArithmeticException.class) |
| public void testUnitizeNullVector() { |
| doTestUnitVectorNullVector(true); |
| } |
| |
| @Test |
| public void testIterator() { |
| final RealVector v = create(values); |
| final Iterator<RealVector.Entry> it = v.iterator(); |
| for (int i = 0; i < values.length; i++) { |
| Assert.assertTrue("entry #" + i, it.hasNext()); |
| final RealVector.Entry e = it.next(); |
| Assert.assertEquals("", i, e.getIndex()); |
| Assert.assertEquals("", values[i], e.getValue(), 0d); |
| try { |
| it.remove(); |
| Assert.fail("MathUnsupportedOperationException should have been thrown"); |
| } catch (MathUnsupportedOperationException exc) { |
| // Expected behavior |
| } |
| } |
| Assert.assertFalse(it.hasNext()); |
| try { |
| it.next(); |
| Assert.fail("NoSuchElementException should have been thrown"); |
| } catch (NoSuchElementException e) { |
| // Expected behavior |
| } |
| } |
| |
| private void doTestCombine(final boolean inPlace, final boolean mixed) { |
| final int n = values.length * values.length; |
| final double[] data1 = new double[n]; |
| final double[] data2 = new double[n]; |
| for (int i = 0; i < values.length; i++) { |
| for (int j = 0; j < values.length; j++) { |
| final int index = values.length * i + j; |
| data1[index] = values[i]; |
| data2[index] = values[j]; |
| } |
| } |
| final RealVector v1 = create(data1); |
| final RealVector v2 = mixed ? createAlien(data2) : create(data2); |
| final double[] expected = new double[n]; |
| for (int i = 0; i < values.length; i++) { |
| final double a1 = values[i]; |
| for (int j = 0; j < values.length; j++) { |
| final double a2 = values[j]; |
| for (int k = 0; k < n; k++) { |
| expected[k] = a1 * data1[k] + a2 * data2[k]; |
| } |
| final RealVector actual; |
| if (inPlace) { |
| final RealVector v1bis = v1.copy(); |
| actual = v1bis.combineToSelf(a1, a2, v2); |
| Assert.assertSame(v1bis, actual); |
| } else { |
| actual = v1.combine(a1, a2, v2); |
| } |
| TestUtils.assertEquals("a1 = " + a1 + ", a2 = " + a2, expected, |
| actual, 0.); |
| } |
| } |
| } |
| |
| private void doTestCombineDimensionMismatch(final boolean inPlace, final boolean mixed) { |
| final RealVector v1 = create(new double[10]); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(new double[15]); |
| } else { |
| v2 = create(new double[15]); |
| } |
| if (inPlace) { |
| v1.combineToSelf(1.0, 1.0, v2); |
| } else { |
| v1.combine(1.0, 1.0, v2); |
| } |
| } |
| |
| @Test |
| public void testCombineSameType() { |
| doTestCombine(false, false); |
| } |
| |
| @Test |
| public void testCombineMixedTypes() { |
| doTestCombine(false, true); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testCombineDimensionMismatchSameType() { |
| doTestCombineDimensionMismatch(false, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testCombineDimensionMismatchMixedTypes() { |
| doTestCombineDimensionMismatch(false, true); |
| } |
| |
| @Test |
| public void testCombineToSelfSameType() { |
| doTestCombine(true, false); |
| } |
| |
| @Test |
| public void testCombineToSelfMixedTypes() { |
| doTestCombine(true, true); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testCombineToSelfDimensionMismatchSameType() { |
| doTestCombineDimensionMismatch(true, false); |
| } |
| |
| @Test(expected = DimensionMismatchException.class) |
| public void testCombineToSelfDimensionMismatchMixedTypes() { |
| doTestCombineDimensionMismatch(true, true); |
| } |
| |
| @Test |
| public void testCopy() { |
| final RealVector v = create(values); |
| final RealVector w = v.copy(); |
| Assert.assertNotSame(v, w); |
| TestUtils.assertEquals("", values, w, 0d); |
| } |
| |
| private void doTestDotProductRegularValues(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = { |
| x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x |
| }; |
| final double[] data2 = { |
| 5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d |
| }; |
| double expected = 0d; |
| for (int i = 0; i < data1.length; i++){ |
| expected += data1[i] * data2[i]; |
| } |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double actual = v1.dotProduct(v2); |
| Assert.assertEquals("", expected, actual, 0d); |
| } |
| |
| private void doTestDotProductSpecialValues(final boolean mixed) { |
| for (int i = 0; i < values.length; i++) { |
| final double[] data1 = { |
| values[i] |
| }; |
| final RealVector v1 = create(data1); |
| for (int j = 0; j < values.length; j++) { |
| final double[] data2 = { |
| values[j] |
| }; |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double expected = data1[0] * data2[0]; |
| final double actual = v1.dotProduct(v2); |
| Assert.assertEquals(data1[0] + " * " + data2[0], expected, |
| actual, 0d); |
| } |
| } |
| } |
| |
| private void doTestDotProductDimensionMismatch(final boolean mixed) { |
| final double[] data1 = new double[10]; |
| final double[] data2 = new double[data1.length + 1]; |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| v1.dotProduct(v2); |
| } |
| |
| @Test |
| public void testDotProductSameType() { |
| doTestDotProductRegularValues(false); |
| doTestDotProductSpecialValues(false); |
| } |
| |
| @Test(expected=DimensionMismatchException.class) |
| public void testDotProductDimensionMismatchSameType() { |
| doTestDotProductDimensionMismatch(false); |
| } |
| |
| @Test |
| public void testDotProductMixedTypes() { |
| doTestDotProductRegularValues(true); |
| doTestDotProductSpecialValues(true); |
| } |
| |
| @Test(expected=DimensionMismatchException.class) |
| public void testDotProductDimensionMismatchMixedTypes() { |
| doTestDotProductDimensionMismatch(true); |
| } |
| |
| private void doTestCosine(final boolean mixed) { |
| final double x = getPreferredEntryValue(); |
| final double[] data1 = { |
| x, 1d, x, x, 2d, x, x, x, 3d, x, x, x, x |
| }; |
| final double[] data2 = { |
| 5d, -6d, 7d, x, x, -8d, -9d, 10d, 11d, x, 12d, 13d, -15d |
| }; |
| double norm1 = 0d; |
| double norm2 = 0d; |
| double dotProduct = 0d; |
| for (int i = 0; i < data1.length; i++){ |
| norm1 += data1[i] * data1[i]; |
| norm2 += data2[i] * data2[i]; |
| dotProduct += data1[i] * data2[i]; |
| } |
| norm1 = FastMath.sqrt(norm1); |
| norm2 = FastMath.sqrt(norm2); |
| final double expected = dotProduct / (norm1 * norm2); |
| final RealVector v1 = create(data1); |
| final RealVector v2; |
| if (mixed) { |
| v2 = createAlien(data2); |
| } else { |
| v2 = create(data2); |
| } |
| final double actual = v1.cosine(v2); |
| Assert.assertEquals("", expected, actual, 0d); |
| |
| } |
| |
| @Test |
| public void testCosineSameType() { |
| doTestCosine(false); |
| } |
| |
| @Test |
| public void testCosineMixedTypes() { |
| doTestCosine(true); |
| } |
| |
| @Test(expected=MathArithmeticException.class) |
| public void testCosineLeftNullVector() { |
| final RealVector v = create(new double[] {0, 0, 0}); |
| final RealVector w = create(new double[] {1, 0, 0}); |
| v.cosine(w); |
| } |
| |
| @Test(expected=MathArithmeticException.class) |
| public void testCosineRightNullVector() { |
| final RealVector v = create(new double[] {0, 0, 0}); |
| final RealVector w = create(new double[] {1, 0, 0}); |
| w.cosine(v); |
| } |
| |
| @Test(expected=DimensionMismatchException.class) |
| public void testCosineDimensionMismatch() { |
| final RealVector v = create(new double[] {1, 2, 3}); |
| final RealVector w = create(new double[] {1, 2, 3, 4}); |
| v.cosine(w); |
| } |
| |
| @Test |
| public void testEquals() { |
| final RealVector v = create(new double[] { 0, 1, 2 }); |
| |
| Assert.assertTrue(v.equals(v)); |
| Assert.assertTrue(v.equals(v.copy())); |
| Assert.assertFalse(v.equals(null)); |
| Assert.assertFalse(v.equals(v.getSubVector(0, v.getDimension() - 1))); |
| Assert.assertTrue(v.equals(v.getSubVector(0, v.getDimension()))); |
| } |
| |
| @Test |
| public void testSerial() { |
| RealVector v = create(new double[] { 0, 1, 2 }); |
| Assert.assertEquals(v,TestUtils.serializeAndRecover(v)); |
| } |
| |
| @Test |
| public void testMinMax() { |
| final RealVector v1 = create(new double[] {0, -6, 4, 12, 7}); |
| Assert.assertEquals(1, v1.getMinIndex()); |
| Assert.assertEquals(-6, v1.getMinValue(), 1.0e-12); |
| Assert.assertEquals(3, v1.getMaxIndex()); |
| Assert.assertEquals(12, v1.getMaxValue(), 1.0e-12); |
| final RealVector v2 = create(new double[] {Double.NaN, 3, Double.NaN, -2}); |
| Assert.assertEquals(3, v2.getMinIndex()); |
| Assert.assertEquals(-2, v2.getMinValue(), 1.0e-12); |
| Assert.assertEquals(1, v2.getMaxIndex()); |
| Assert.assertEquals(3, v2.getMaxValue(), 1.0e-12); |
| final RealVector v3 = create(new double[] {Double.NaN, Double.NaN}); |
| Assert.assertEquals(-1, v3.getMinIndex()); |
| Assert.assertTrue(Double.isNaN(v3.getMinValue())); |
| Assert.assertEquals(-1, v3.getMaxIndex()); |
| Assert.assertTrue(Double.isNaN(v3.getMaxValue())); |
| final RealVector v4 = create(new double[0]); |
| Assert.assertEquals(-1, v4.getMinIndex()); |
| Assert.assertTrue(Double.isNaN(v4.getMinValue())); |
| Assert.assertEquals(-1, v4.getMaxIndex()); |
| Assert.assertTrue(Double.isNaN(v4.getMaxValue())); |
| } |
| |
| /* |
| * TESTS OF THE VISITOR PATTERN |
| */ |
| |
| /** The whole vector is visited. */ |
| @Test |
| public void testWalkInDefaultOrderPreservingVisitor1() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final RealVector v = create(data); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| |
| private int expectedIndex; |
| |
| @Override |
| public void visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(expectedIndex, actualIndex); |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| ++expectedIndex; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(0, actualStart); |
| Assert.assertEquals(data.length - 1, actualEnd); |
| expectedIndex = 0; |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| v.walkInDefaultOrder(visitor); |
| } |
| |
| /** Visiting an invalid subvector. */ |
| @Test |
| public void testWalkInDefaultOrderPreservingVisitor2() { |
| final RealVector v = create(new double[5]); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| |
| @Override |
| public void visit(int index, double value) { |
| // Do nothing |
| } |
| |
| @Override |
| public void start(int dimension, int start, int end) { |
| // Do nothing |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| try { |
| v.walkInDefaultOrder(visitor, -1, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 5, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 0, -1); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 0, 5); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 4, 0); |
| Assert.fail(); |
| } catch (NumberIsTooSmallException e) { |
| // Expected behavior |
| } |
| } |
| |
| /** Visiting a valid subvector. */ |
| @Test |
| public void testWalkInDefaultOrderPreservingVisitor3() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final int expectedStart = 2; |
| final int expectedEnd = 7; |
| final RealVector v = create(data); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| |
| private int expectedIndex; |
| |
| @Override |
| public void visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(expectedIndex, actualIndex); |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| ++expectedIndex; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(expectedStart, actualStart); |
| Assert.assertEquals(expectedEnd, actualEnd); |
| expectedIndex = expectedStart; |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); |
| } |
| |
| /** The whole vector is visited. */ |
| @Test |
| public void testWalkInOptimizedOrderPreservingVisitor1() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final RealVector v = create(data); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| private final boolean[] visited = new boolean[data.length]; |
| |
| @Override |
| public void visit(final int actualIndex, final double actualValue) { |
| visited[actualIndex] = true; |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(0, actualStart); |
| Assert.assertEquals(data.length - 1, actualEnd); |
| Arrays.fill(visited, false); |
| } |
| |
| @Override |
| public double end() { |
| for (int i = 0; i < data.length; i++) { |
| Assert.assertTrue("entry " + i + "has not been visited", |
| visited[i]); |
| } |
| return 0.0; |
| } |
| }; |
| v.walkInOptimizedOrder(visitor); |
| } |
| |
| /** Visiting an invalid subvector. */ |
| @Test |
| public void testWalkInOptimizedOrderPreservingVisitor2() { |
| final RealVector v = create(new double[5]); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| |
| @Override |
| public void visit(int index, double value) { |
| // Do nothing |
| } |
| |
| @Override |
| public void start(int dimension, int start, int end) { |
| // Do nothing |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| try { |
| v.walkInOptimizedOrder(visitor, -1, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 5, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 0, -1); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 0, 5); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 4, 0); |
| Assert.fail(); |
| } catch (NumberIsTooSmallException e) { |
| // Expected behavior |
| } |
| } |
| |
| /** Visiting a valid subvector. */ |
| @Test |
| public void testWalkInOptimizedOrderPreservingVisitor3() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final int expectedStart = 2; |
| final int expectedEnd = 7; |
| final RealVector v = create(data); |
| final RealVectorPreservingVisitor visitor; |
| visitor = new RealVectorPreservingVisitor() { |
| private final boolean[] visited = new boolean[data.length]; |
| |
| @Override |
| public void visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| visited[actualIndex] = true; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(expectedStart, actualStart); |
| Assert.assertEquals(expectedEnd, actualEnd); |
| Arrays.fill(visited, true); |
| } |
| |
| @Override |
| public double end() { |
| for (int i = expectedStart; i <= expectedEnd; i++) { |
| Assert.assertTrue("entry " + i + "has not been visited", |
| visited[i]); |
| } |
| return 0.0; |
| } |
| }; |
| v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd); |
| } |
| |
| /** The whole vector is visited. */ |
| @Test |
| public void testWalkInDefaultOrderChangingVisitor1() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final RealVector v = create(data); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| |
| private int expectedIndex; |
| |
| @Override |
| public double visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(expectedIndex, actualIndex); |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| ++expectedIndex; |
| return actualIndex + actualValue; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(0, actualStart); |
| Assert.assertEquals(data.length - 1, actualEnd); |
| expectedIndex = 0; |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| v.walkInDefaultOrder(visitor); |
| for (int i = 0; i < data.length; i++) { |
| Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); |
| } |
| } |
| |
| /** Visiting an invalid subvector. */ |
| @Test |
| public void testWalkInDefaultOrderChangingVisitor2() { |
| final RealVector v = create(new double[5]); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| |
| @Override |
| public double visit(int index, double value) { |
| return 0.0; |
| } |
| |
| @Override |
| public void start(int dimension, int start, int end) { |
| // Do nothing |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| try { |
| v.walkInDefaultOrder(visitor, -1, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 5, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 0, -1); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 0, 5); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInDefaultOrder(visitor, 4, 0); |
| Assert.fail(); |
| } catch (NumberIsTooSmallException e) { |
| // Expected behavior |
| } |
| } |
| |
| /** Visiting a valid subvector. */ |
| @Test |
| public void testWalkInDefaultOrderChangingVisitor3() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final int expectedStart = 2; |
| final int expectedEnd = 7; |
| final RealVector v = create(data); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| |
| private int expectedIndex; |
| |
| @Override |
| public double visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(expectedIndex, actualIndex); |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| ++expectedIndex; |
| return actualIndex + actualValue; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(expectedStart, actualStart); |
| Assert.assertEquals(expectedEnd, actualEnd); |
| expectedIndex = expectedStart; |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| v.walkInDefaultOrder(visitor, expectedStart, expectedEnd); |
| for (int i = expectedStart; i <= expectedEnd; i++) { |
| Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); |
| } |
| } |
| |
| /** The whole vector is visited. */ |
| @Test |
| public void testWalkInOptimizedOrderChangingVisitor1() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final RealVector v = create(data); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| private final boolean[] visited = new boolean[data.length]; |
| |
| @Override |
| public double visit(final int actualIndex, final double actualValue) { |
| visited[actualIndex] = true; |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| return actualIndex + actualValue; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(0, actualStart); |
| Assert.assertEquals(data.length - 1, actualEnd); |
| Arrays.fill(visited, false); |
| } |
| |
| @Override |
| public double end() { |
| for (int i = 0; i < data.length; i++) { |
| Assert.assertTrue("entry " + i + "has not been visited", |
| visited[i]); |
| } |
| return 0.0; |
| } |
| }; |
| v.walkInOptimizedOrder(visitor); |
| for (int i = 0; i < data.length; i++) { |
| Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); |
| } |
| } |
| |
| /** Visiting an invalid subvector. */ |
| @Test |
| public void testWalkInOptimizedOrderChangingVisitor2() { |
| final RealVector v = create(new double[5]); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| |
| @Override |
| public double visit(int index, double value) { |
| return 0.0; |
| } |
| |
| @Override |
| public void start(int dimension, int start, int end) { |
| // Do nothing |
| } |
| |
| @Override |
| public double end() { |
| return 0.0; |
| } |
| }; |
| try { |
| v.walkInOptimizedOrder(visitor, -1, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 5, 4); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 0, -1); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 0, 5); |
| Assert.fail(); |
| } catch (OutOfRangeException e) { |
| // Expected behavior |
| } |
| try { |
| v.walkInOptimizedOrder(visitor, 4, 0); |
| Assert.fail(); |
| } catch (NumberIsTooSmallException e) { |
| // Expected behavior |
| } |
| } |
| |
| /** Visiting a valid subvector. */ |
| @Test |
| public void testWalkInOptimizedOrderChangingVisitor3() { |
| final double[] data = new double[] { |
| 0d, 1d, 0d, 0d, 2d, 0d, 0d, 0d, 3d |
| }; |
| final int expectedStart = 2; |
| final int expectedEnd = 7; |
| final RealVector v = create(data); |
| final RealVectorChangingVisitor visitor; |
| visitor = new RealVectorChangingVisitor() { |
| private final boolean[] visited = new boolean[data.length]; |
| |
| @Override |
| public double visit(final int actualIndex, final double actualValue) { |
| Assert.assertEquals(Integer.toString(actualIndex), |
| data[actualIndex], actualValue, 0d); |
| visited[actualIndex] = true; |
| return actualIndex + actualValue; |
| } |
| |
| @Override |
| public void start(final int actualSize, final int actualStart, |
| final int actualEnd) { |
| Assert.assertEquals(data.length, actualSize); |
| Assert.assertEquals(expectedStart, actualStart); |
| Assert.assertEquals(expectedEnd, actualEnd); |
| Arrays.fill(visited, true); |
| } |
| |
| @Override |
| public double end() { |
| for (int i = expectedStart; i <= expectedEnd; i++) { |
| Assert.assertTrue("entry " + i + "has not been visited", |
| visited[i]); |
| } |
| return 0.0; |
| } |
| }; |
| v.walkInOptimizedOrder(visitor, expectedStart, expectedEnd); |
| for (int i = expectedStart; i <= expectedEnd; i++) { |
| Assert.assertEquals("entry " + i, i + data[i], v.getEntry(i), 0.0); |
| } |
| } |
| |
| /** |
| * Minimal implementation of the {@link RealVector} abstract class, for |
| * mixed types unit tests. |
| */ |
| public static class RealVectorTestImpl extends RealVector |
| implements Serializable { |
| |
| /** Serializable version identifier. */ |
| private static final long serialVersionUID = 20120706L; |
| |
| /** Entries of the vector. */ |
| protected double data[]; |
| |
| public RealVectorTestImpl(double[] d) { |
| data = d.clone(); |
| } |
| |
| private UnsupportedOperationException unsupported() { |
| return new UnsupportedOperationException("Not supported, unneeded for test purposes"); |
| } |
| |
| @Override |
| public RealVector copy() { |
| return new RealVectorTestImpl(data); |
| } |
| |
| @Override |
| public RealVector ebeMultiply(RealVector v) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public RealVector ebeDivide(RealVector v) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public double getEntry(int index) { |
| checkIndex(index); |
| return data[index]; |
| } |
| |
| @Override |
| public int getDimension() { |
| return data.length; |
| } |
| |
| @Override |
| public RealVector append(RealVector v) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public RealVector append(double d) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public RealVector getSubVector(int index, int n) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public void setEntry(int index, double value) { |
| checkIndex(index); |
| data[index] = value; |
| } |
| |
| @Override |
| public void setSubVector(int index, RealVector v) { |
| throw unsupported(); |
| } |
| |
| @Override |
| public boolean isNaN() { |
| throw unsupported(); |
| } |
| |
| @Override |
| public boolean isInfinite() { |
| throw unsupported(); |
| } |
| } |
| } |