Author: erans
Date: Wed Jul 27 23:26:45 2011
New Revision: 1151665

URL: http://svn.apache.org/viewvc?rev=1151665&view=rev
Log:
MATH-613
Linear combination of vectors.

Modified:
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
    
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/RealVector.java
    commons/proper/math/trunk/src/site/xdoc/changes.xml
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
    
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/AbstractRealVector.java
 Wed Jul 27 23:26:45 2011
@@ -514,6 +514,32 @@ public abstract class AbstractRealVector
         return this;
     }
 
+    /** {@inheritDoc} */
+    public RealVector combine(double a, double b, double[] y) {
+        return copy().combineToSelf(a, b, y);
+    }
+
+    /** {@inheritDoc} */
+    public RealVector combine(double a, double b, RealVector y) {
+        return copy().combineToSelf(a, b, y);
+    }
+
+    /** {@inheritDoc} */
+    public RealVector combineToSelf(double a, double b, double[] y) {
+        return combineToSelf(a, b, new ArrayRealVector(y, false));
+    }
+
+    /** {@inheritDoc} */
+    public RealVector combineToSelf(double a, double b, RealVector y) {
+        checkVectorDimensions(y);
+        for (int i = 0; i < getDimension(); i++) {
+            final double xi = getEntry(i);
+            final double yi = y.getEntry(i);
+            setEntry(i, a * xi + b * yi);
+        }
+        return this;
+    }
+
     /** An entry in the vector. */
     protected class EntryImpl extends Entry {
 

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/ArrayRealVector.java
 Wed Jul 27 23:26:45 2011
@@ -1045,4 +1045,60 @@ public class ArrayRealVector extends Abs
         }
         return MathUtils.hash(data);
     }
+
+    /**
+     * Returns the linear combination of {@code this} and {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return a vector containing {@code a * this[i] + b * y[i]} for all
+     * {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    public ArrayRealVector combine(double a, double b, ArrayRealVector y) {
+        return (ArrayRealVector) copy().combineToSelf(a, b, y.data);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public RealVector combineToSelf(double a, double b, double[] y) {
+        checkVectorDimensions(y.length);
+        for (int i = 0; i < this.data.length; i++) {
+            data[i] = a * data[i] + b * y[i];
+        }
+        return this;
+    }
+
+    /**
+     * Updates {@code this} with the linear combination of {@code this} and
+     * {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return {@code this}, with components equal to
+     * {@code a * this[i] + b * y[i]} for all {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    public ArrayRealVector combineToSelf(double a, double b, ArrayRealVector 
y) {
+        combineToSelf(a, b, y.data);
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public RealVector combineToSelf(double a, double b, RealVector y) {
+        if (y instanceof ArrayRealVector) {
+            return combineToSelf(a, b, ((ArrayRealVector) y).data);
+        } else {
+            checkVectorDimensions(y);
+            for (int i = 0; i < this.data.length; i++) {
+                data[i] = a * data[i] + b * y.getEntry(i);
+            }
+            return this;
+        }
+    }
 }

Modified: 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/RealVector.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/RealVector.java?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/RealVector.java
 (original)
+++ 
commons/proper/math/trunk/src/main/java/org/apache/commons/math/linear/RealVector.java
 Wed Jul 27 23:26:45 2011
@@ -597,4 +597,58 @@ public interface RealVector {
      * none are {@code NaN}, {@code false} otherwise.
      */
     boolean isInfinite();
+
+    /**
+     * Returns the linear combination of {@code this} and {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return a vector containing {@code a * this[i] + b * y[i]} for all
+     * {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    RealVector combine(double a, double b, double[] y);
+
+    /**
+     * Returns the linear combination of {@code this} and {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return a vector containing {@code a * this[i] + b * y[i]} for all
+     * {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    RealVector combine(double a, double b, RealVector y);
+
+    /**
+     * Updates {@code this} with the linear combination of {@code this} and
+     * {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return {@code this}, with components equal to
+     * {@code a * this[i] + b * y[i]} for all {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    RealVector combineToSelf(double a, double b, double[] y);
+
+    /**
+     * Updates {@code this} with the linear combination of {@code this} and
+     * {@code y}.
+     *
+     * @param a Weight of {@code this}.
+     * @param b Weight of {@code y}.
+     * @param y Vector with which {@code this} is linearly combined.
+     * @return {@code this}, with components equal to
+     * {@code a * this[i] + b * y[i]} for all {@code i}.
+     * @throws org.apache.commons.math.exception.DimensionMismatchException
+     * if {@code y} is not the same size as this vector.
+     */
+    RealVector combineToSelf(double a, double b, RealVector y);
 }

Modified: commons/proper/math/trunk/src/site/xdoc/changes.xml
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/site/xdoc/changes.xml?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- commons/proper/math/trunk/src/site/xdoc/changes.xml (original)
+++ commons/proper/math/trunk/src/site/xdoc/changes.xml Wed Jul 27 23:26:45 2011
@@ -52,6 +52,10 @@ The <action> type attribute can be add,u
     If the output is not quite correct, check for invisible trailing spaces!
      -->
     <release version="3.0" date="TBD" description="TBD">
+      <action dev="erans" type="add" issue="MATH-613" due-to="Sébastien 
Brisard">
+        Linear combination of vectors: "RealVector" interface updated, 
implemented
+        in "AbstractRealVector" and "ArrayRealVector".
+      </action>
       <action dev="erans" type="update" issue="MATH-623" due-to="Arne Plöse">
         Slightly more efficient implementation of basic operations in
         "ArrayRealVector".

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/AbstractRealVectorTest.java
 Wed Jul 27 23:26:45 2011
@@ -20,6 +20,7 @@ package org.apache.commons.math.linear;
 import org.junit.Test;
 import org.junit.Assert;
 import org.apache.commons.math.analysis.UnivariateRealFunction;
+import org.apache.commons.math.exception.DimensionMismatchException;
 import org.apache.commons.math.linear.RealVector.Entry;
 import java.util.Iterator;
 import java.util.Random;
@@ -200,7 +201,7 @@ public class AbstractRealVectorTest {
         for(Iterator<Entry> it = v.sparseIterator(); it.hasNext() && (e = 
it.next()) != null; ) {
             Assert.assertEquals(onlyOne[1], e.getValue(), 0);
         }
-        
+
     }
 
     @Test
@@ -216,4 +217,86 @@ public class AbstractRealVectorTest {
         Assert.assertEquals(new ArrayRealVector(d).getNorm(), new 
ArrayRealVector(c).getNorm(), 0);
     }
 
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombinePrecondition() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final TestVectorImpl x = new TestVectorImpl(aux);
+        aux = new double[] { 6d, 7d };
+        final TestVectorImpl y = new TestVectorImpl(aux);
+        x.combine(a, b, y);
+    }
+
+    @Test
+    public void testCombine() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new TestVectorImpl(new double[dim]);
+        final RealVector y = new TestVectorImpl(new double[dim]);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        final RealVector z = x.combine(a, b, y);
+        Assert.assertTrue(z != x);
+        final double[] actual = z.getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ", expected[i],
+                                actual[i], delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombineToSelfPrecondition() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final TestVectorImpl x = new TestVectorImpl(aux);
+        aux = new double[] { 6d, 7d };
+        final TestVectorImpl y = new TestVectorImpl(aux);
+        x.combineToSelf(a, b, y);
+    }
+
+    @Test
+    public void testCombineToSelf() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new TestVectorImpl(new double[dim]);
+        final RealVector y = new TestVectorImpl(new double[dim]);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        Assert.assertSame(x, x.combineToSelf(a, b, y));
+        final double[] actual = x.getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ", expected[i],
+                                actual[i], delta);
+        }
+    }
 }

Modified: 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
URL: 
http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java?rev=1151665&r1=1151664&r2=1151665&view=diff
==============================================================================
--- 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
 (original)
+++ 
commons/proper/math/trunk/src/test/java/org/apache/commons/math/linear/ArrayRealVectorTest.java
 Wed Jul 27 23:26:45 2011
@@ -18,40 +18,41 @@ package org.apache.commons.math.linear;
 
 import java.io.Serializable;
 import java.util.Iterator;
-import org.junit.Assert;
-import org.junit.Test;
+import java.util.Random;
 
 import org.apache.commons.math.TestUtils;
 import org.apache.commons.math.analysis.UnivariateRealFunction;
-import org.apache.commons.math.util.FastMath;
-import org.apache.commons.math.exception.OutOfRangeException;
-import org.apache.commons.math.exception.MathIllegalArgumentException;
-import org.apache.commons.math.exception.MathArithmeticException;
-import org.apache.commons.math.exception.DimensionMismatchException;
 import org.apache.commons.math.analysis.function.Abs;
 import org.apache.commons.math.analysis.function.Acos;
 import org.apache.commons.math.analysis.function.Asin;
 import org.apache.commons.math.analysis.function.Atan;
 import org.apache.commons.math.analysis.function.Cbrt;
-import org.apache.commons.math.analysis.function.Cosh;
+import org.apache.commons.math.analysis.function.Ceil;
 import org.apache.commons.math.analysis.function.Cos;
+import org.apache.commons.math.analysis.function.Cosh;
 import org.apache.commons.math.analysis.function.Exp;
 import org.apache.commons.math.analysis.function.Expm1;
+import org.apache.commons.math.analysis.function.Floor;
 import org.apache.commons.math.analysis.function.Inverse;
+import org.apache.commons.math.analysis.function.Log;
 import org.apache.commons.math.analysis.function.Log10;
 import org.apache.commons.math.analysis.function.Log1p;
-import org.apache.commons.math.analysis.function.Log;
-import org.apache.commons.math.analysis.function.Sinh;
+import org.apache.commons.math.analysis.function.Power;
+import org.apache.commons.math.analysis.function.Rint;
+import org.apache.commons.math.analysis.function.Signum;
 import org.apache.commons.math.analysis.function.Sin;
+import org.apache.commons.math.analysis.function.Sinh;
 import org.apache.commons.math.analysis.function.Sqrt;
-import org.apache.commons.math.analysis.function.Tanh;
 import org.apache.commons.math.analysis.function.Tan;
-import org.apache.commons.math.analysis.function.Floor;
-import org.apache.commons.math.analysis.function.Ceil;
-import org.apache.commons.math.analysis.function.Rint;
-import org.apache.commons.math.analysis.function.Signum;
+import org.apache.commons.math.analysis.function.Tanh;
 import org.apache.commons.math.analysis.function.Ulp;
-import org.apache.commons.math.analysis.function.Power;
+import org.apache.commons.math.exception.DimensionMismatchException;
+import org.apache.commons.math.exception.MathArithmeticException;
+import org.apache.commons.math.exception.MathIllegalArgumentException;
+import org.apache.commons.math.exception.OutOfRangeException;
+import org.apache.commons.math.util.FastMath;
+import org.junit.Assert;
+import org.junit.Test;
 
 /**
  * Test cases for the {@link ArrayRealVector} class.
@@ -342,6 +343,21 @@ public class ArrayRealVectorTest {
             throw unsupported();
         }
 
+        public RealVector combine(double a, double b, double[] y) {
+            throw unsupported();
+        }
+
+        public RealVector combine(double a, double b, RealVector y) {
+            throw unsupported();
+        }
+
+        public RealVector combineToSelf(double a, double b, double[] y) {
+            throw unsupported();
+        }
+
+        public RealVector combineToSelf(double a, double b, RealVector y) {
+            throw unsupported();
+        }
     }
 
     @Test
@@ -1206,6 +1222,259 @@ public class ArrayRealVectorTest {
         Assert.assertEquals(6, uv.getEntry(2, 1), tol);
     }
 
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombinePreconditionArray() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        final double[] y = new double[] { 6d, 7d };
+        x.combine(a, b, y);
+    }
+
+    @Test
+    public void testCombineArray() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final double[] y = new double[dim];
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y[i] = yi;
+            expected[i] = a * xi + b * yi;
+        }
+        final double[] actual = x.combine(a, b, y).getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombinePreconditionSameType() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        aux = new double[] { 6d, 7d };
+        final RealVector y = new ArrayRealVector(aux, false);
+        x.combine(a, b, y);
+    }
+
+    @Test
+    public void testCombineSameType() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final RealVector y = new ArrayRealVector(dim);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        final double[] actual = x.combine(a, b, y).getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombinePreconditionMixedType() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        aux = new double[] { 6d, 7d };
+        final RealVector y = new OpenMapRealVector(aux);
+        x.combine(a, b, y);
+    }
+
+    @Test
+    public void testCombineMixedTypes() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final RealVector y = new OpenMapRealVector(dim, 0d);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        final double[] actual = x.combine(a, b, y).getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombineToSelfPreconditionArray() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        final double[] y = new double[] { 6d, 7d };
+        x.combineToSelf(a, b, y);
+    }
+
+    @Test
+    public void testCombineToSelfArray() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final double[] y = new double[dim];
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y[i] = yi;
+            expected[i] = a * xi + b * yi;
+        }
+        Assert.assertSame(x, x.combineToSelf(a, b, y));
+        final double[] actual = x.getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombineToSelfPreconditionSameType() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        aux = new double[] { 6d, 7d };
+        final RealVector y = new ArrayRealVector(aux, false);
+        x.combineToSelf(a, b, y);
+    }
+
+    @Test
+    public void testCombineToSelfSameType() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final RealVector y = new ArrayRealVector(dim);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        Assert.assertSame(x, x.combineToSelf(a, b, y));
+        final double[] actual = x.getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
+    @Test(expected=DimensionMismatchException.class)
+    public void testCombineToSelfPreconditionMixedType() {
+        final double a = 1d;
+        final double b = 2d;
+        double[] aux = new double[] { 3d, 4d, 5d };
+        final RealVector x = new ArrayRealVector(aux, false);
+        aux = new double[] { 6d, 7d };
+        final RealVector y = new OpenMapRealVector(aux);
+        x.combineToSelf(a, b, y);
+    }
+
+    @Test
+    public void testCombineToSelfMixedTypes() {
+        final Random random = new Random(20110726);
+        final int dim = 10;
+        final double a = (2 * random.nextDouble() - 1);
+        final double b = (2 * random.nextDouble() - 1);
+        final RealVector x = new ArrayRealVector(dim);
+        final RealVector y = new OpenMapRealVector(dim, 0d);
+        final double[] expected = new double[dim];
+        for (int i = 0; i < dim; i++) {
+            final double xi = 2 * random.nextDouble() - 1;
+            final double yi = 2 * random.nextDouble() - 1;
+            x.setEntry(i, xi);
+            y.setEntry(i, yi);
+            expected[i] = a * xi + b * yi;
+        }
+        Assert.assertSame(x, x.combineToSelf(a, b, y));
+        final double[] actual = x.getData();
+        for (int i = 0; i < dim; i++) {
+            final double delta;
+            if (expected[i] == 0d) {
+                delta = Math.ulp(1d);
+            } else {
+                delta = Math.ulp(expected[i]);
+            }
+            Assert.assertEquals("elements [" + i + "] differ",
+                                expected[i],
+                                actual[i],
+                                delta);
+        }
+    }
+
     /** verifies that two vectors are close (sup norm) */
     protected void assertClose(String msg, double[] m, double[] n,
             double tolerance) {


Reply via email to