commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From l..@apache.org
Subject svn commit: r1446210 - in /commons/proper/math/trunk/src: changes/changes.xml main/java/org/apache/commons/math3/util/MathArrays.java test/java/org/apache/commons/math3/util/MathArraysTest.java
Date Thu, 14 Feb 2013 14:43:16 GMT
Author: luc
Date: Thu Feb 14 14:43:15 2013
New Revision: 1446210

URL: http://svn.apache.org/r1446210
Log:
Added accurate linear combinations for DerivativeStructure instances.

Modified:
    commons/proper/math/trunk/src/changes/changes.xml
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/MathArrays.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/MathArraysTest.java

Modified: commons/proper/math/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/changes/changes.xml?rev=1446210&r1=1446209&r2=1446210&view=diff
==============================================================================
--- commons/proper/math/trunk/src/changes/changes.xml (original)
+++ commons/proper/math/trunk/src/changes/changes.xml Thu Feb 14 14:43:15 2013
@@ -55,6 +55,10 @@ This is a minor release: It combines bug
   Changes to existing features were made in a backwards-compatible
   way such as to allow drop-in replacement of the v3.1[.1] JAR file.
 ">
+      <action dev="luc" type="add" >
+        Added accurate linear combination of DerivativeStructure instances,
+        avoiding cancellation.  
+      </action>
       <action dev="erans" type="update" issue="MATH-933">
         Throw "MathUnsupportedOperationException" from optimizers that do
         not support constraints (previous behaviour was to silently ignore

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/MathArrays.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/MathArrays.java?rev=1446210&r1=1446209&r2=1446210&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/MathArrays.java
(original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/MathArrays.java
Thu Feb 14 14:43:15 2013
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Collections;
 
+import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
 import org.apache.commons.math3.exception.DimensionMismatchException;
 import org.apache.commons.math3.exception.MathInternalError;
 import org.apache.commons.math3.exception.NonMonotonicSequenceException;
@@ -1118,6 +1119,353 @@ public class MathArrays {
     }
 
     /**
+     * Compute a linear combination accurately.
+     * This method computes the sum of the products
+     * <code>a<sub>i</sub> b<sub>i</sub></code> to high
accuracy.
+     * It does so by using specific multiplication and addition algorithms to
+     * preserve accuracy and reduce cancellation effects.
+     * <br/>
+     * It is based on the 2005 paper
+     * <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump,
+     * and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     *
+     * @param a Factors.
+     * @param b Factors.
+     * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub>
b<sub>i</sub></code>.
+     * @throws DimensionMismatchException if arrays dimensions don't match
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final DerivativeStructure[] a, final
DerivativeStructure[] b)
+        throws DimensionMismatchException {
+
+        // compute an accurate value, taking care of cancellations
+        final double[] aDouble = new double[a.length];
+        for (int i = 0; i < a.length; ++i) {
+            aDouble[i] = a[i].getValue();
+        }
+        final double[] bDouble = new double[b.length];
+        for (int i = 0; i < b.length; ++i) {
+            bDouble[i] = b[i].getValue();
+        }
+        final double accurateValue = MathArrays.linearCombination(aDouble, bDouble);
+
+        // compute a simple value, with all partial derivatives
+        DerivativeStructure simpleValue = a[0].getField().getZero();
+        for (int i = 0; i < a.length; ++i) {
+            simpleValue = simpleValue.add(a[i].multiply(b[i]));
+        }
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * This method computes the sum of the products
+     * <code>a<sub>i</sub> b<sub>i</sub></code> to high
accuracy.
+     * It does so by using specific multiplication and addition algorithms to
+     * preserve accuracy and reduce cancellation effects.
+     * <br/>
+     * It is based on the 2005 paper
+     * <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita, Siegfried M. Rump,
+     * and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     *
+     * @param a Factors.
+     * @param b Factors.
+     * @return <code>&Sigma;<sub>i</sub> a<sub>i</sub>
b<sub>i</sub></code>.
+     * @throws DimensionMismatchException if arrays dimensions don't match
+     */
+    public static DerivativeStructure linearCombination(final double[] a, final DerivativeStructure[]
b)
+        throws DimensionMismatchException {
+
+        // compute an accurate value, taking care of cancellations
+        final double[] bDouble = new double[b.length];
+        for (int i = 0; i < b.length; ++i) {
+            bDouble[i] = b[i].getValue();
+        }
+        final double accurateValue = MathArrays.linearCombination(a, bDouble);
+
+        // compute a simple value, with all partial derivatives
+        DerivativeStructure simpleValue = b[0].getField().getZero();
+        for (int i = 0; i < a.length; ++i) {
+            simpleValue = simpleValue.add(b[i].multiply(a[i]));
+        }
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub>
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure, DerivativeStructure, DerivativeStructure)
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure, DerivativeStructure, DerivativeStructure, DerivativeStructure, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final DerivativeStructure a1, final
DerivativeStructure b1,
+                                                        final DerivativeStructure a2, final
DerivativeStructure b2) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1.getValue(), b1.getValue(),
+                                                                  a2.getValue(), b2.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub>
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure,
double, DerivativeStructure)
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure,
double, DerivativeStructure, double, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final double a1, final DerivativeStructure
b1,
+                                                        final double a2, final DerivativeStructure
b2) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1, b1.getValue(),
+                                                                  a2, b2.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @param a3 first factor of the third term
+     * @param b3 second factor of the third term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure)
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure, DerivativeStructure, DerivativeStructure, DerivativeStructure, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final DerivativeStructure a1, final
DerivativeStructure b1,
+                                                        final DerivativeStructure a2, final
DerivativeStructure b2,
+                                                        final DerivativeStructure a3, final
DerivativeStructure b3) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1.getValue(), b1.getValue(),
+                                                                  a2.getValue(), b2.getValue(),
+                                                                  a3.getValue(), b3.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @param a3 first factor of the third term
+     * @param b3 second factor of the third term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure)
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure,
double, DerivativeStructure, double, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final double a1, final DerivativeStructure
b1,
+                                                        final double a2, final DerivativeStructure
b2,
+                                                        final double a3, final DerivativeStructure
b3) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1, b1.getValue(),
+                                                                  a2, b2.getValue(),
+                                                                  a3, b3.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+
+     * a<sub>4</sub>&times;b<sub>4</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @param a3 first factor of the third term
+     * @param b3 second factor of the third term
+     * @param a4 first factor of the third term
+     * @param b4 second factor of the third term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+
+     * a<sub>4</sub>&times;b<sub>4</sub>
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure)
+     * @see #linearCombination(DerivativeStructure, DerivativeStructure, DerivativeStructure,
DerivativeStructure, DerivativeStructure, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final DerivativeStructure a1, final
DerivativeStructure b1,
+                                                        final DerivativeStructure a2, final
DerivativeStructure b2,
+                                                        final DerivativeStructure a3, final
DerivativeStructure b3,
+                                                        final DerivativeStructure a4, final
DerivativeStructure b4) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1.getValue(), b1.getValue(),
+                                                                  a2.getValue(), b2.getValue(),
+                                                                  a3.getValue(), b3.getValue(),
+                                                                  a4.getValue(), b4.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = a1.multiply(b1).add(a2.multiply(b2)).add(a3.multiply(b3)).add(a4.multiply(b4));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
+     * Compute a linear combination accurately.
+     * <p>
+     * This method computes a<sub>1</sub>&times;b<sub>1</sub>
+
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+
+     * a<sub>4</sub>&times;b<sub>4</sub>
+     * to high accuracy. It does so by using specific multiplication and
+     * addition algorithms to preserve accuracy and reduce cancellation effects.
+     * It is based on the 2005 paper <a
+     * href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.2.1547">
+     * Accurate Sum and Dot Product</a> by Takeshi Ogita,
+     * Siegfried M. Rump, and Shin'ichi Oishi published in SIAM J. Sci. Comput.
+     * </p>
+     * @param a1 first factor of the first term
+     * @param b1 second factor of the first term
+     * @param a2 first factor of the second term
+     * @param b2 second factor of the second term
+     * @param a3 first factor of the third term
+     * @param b3 second factor of the third term
+     * @param a4 first factor of the third term
+     * @param b4 second factor of the third term
+     * @return a<sub>1</sub>&times;b<sub>1</sub> +
+     * a<sub>2</sub>&times;b<sub>2</sub> + a<sub>3</sub>&times;b<sub>3</sub>
+
+     * a<sub>4</sub>&times;b<sub>4</sub>
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure)
+     * @see #linearCombination(double, DerivativeStructure, double, DerivativeStructure,
double, DerivativeStructure)
+     * @since 3.2
+     */
+    public static DerivativeStructure linearCombination(final double a1, final DerivativeStructure
b1,
+                                                        final double a2, final DerivativeStructure
b2,
+                                                        final double a3, final DerivativeStructure
b3,
+                                                        final double a4, final DerivativeStructure
b4) {
+
+        // compute an accurate value, taking care of cancellations
+        final double accurateValue = MathArrays.linearCombination(a1, b1.getValue(),
+                                                                  a2, b2.getValue(),
+                                                                  a3, b3.getValue(),
+                                                                  a4, b4.getValue());
+
+        // compute a simple value, with all partial derivatives
+        final DerivativeStructure simpleValue = b1.multiply(a1).add(b2.multiply(a2)).add(b3.multiply(a3)).add(b4.multiply(a4));
+
+        // create a result with accurate value and all derivatives (not necessarily as accurate
as the value)
+        final double[] data = simpleValue.getAllDerivatives();
+        data[0] = accurateValue;
+        return new DerivativeStructure(simpleValue.getFreeParameters(), simpleValue.getOrder(),
data);
+
+    }
+
+    /**
      * Returns true iff both arguments are null or have same dimensions and all
      * their elements are equal as defined by
      * {@link Precision#equals(float,float)}.

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/MathArraysTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/MathArraysTest.java?rev=1446210&r1=1446209&r2=1446210&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/MathArraysTest.java
(original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/util/MathArraysTest.java
Thu Feb 14 14:43:15 2013
@@ -14,6 +14,8 @@
 package org.apache.commons.math3.util;
 
 import java.util.Arrays;
+
+import org.apache.commons.math3.analysis.differentiation.DerivativeStructure;
 import org.apache.commons.math3.exception.NonMonotonicSequenceException;
 import org.apache.commons.math3.exception.DimensionMismatchException;
 import org.apache.commons.math3.exception.NotPositiveException;
@@ -537,6 +539,11 @@ public class MathArraysTest {
         final double abSumArray = MathArrays.linearCombination(a, b);
 
         Assert.assertEquals(abSumInline, abSumArray, 0);
+        Assert.assertEquals(-1.8551294182586248737720779899, abSumInline, 1.0e-15);
+
+        final double naive = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+        Assert.assertTrue(FastMath.abs(naive - abSumInline) > 1.5);
+
     }
 
     @Test
@@ -714,6 +721,149 @@ public class MathArraysTest {
     }
 
     @Test
+    public void testLinearCombination1DSDS() {
+        final DerivativeStructure[] a = new DerivativeStructure[] {
+            new DerivativeStructure(6, 1, 0, -1321008684645961.0 / 268435456.0),
+            new DerivativeStructure(6, 1, 1, -5774608829631843.0 / 268435456.0),
+            new DerivativeStructure(6, 1, 2, -7645843051051357.0 / 8589934592.0)
+        };
+        final DerivativeStructure[] b = new DerivativeStructure[] {
+            new DerivativeStructure(6, 1, 3, -5712344449280879.0 / 2097152.0),
+            new DerivativeStructure(6, 1, 4, -4550117129121957.0 / 2097152.0),
+            new DerivativeStructure(6, 1, 5, 8846951984510141.0 / 131072.0)
+        };
+
+        final DerivativeStructure abSumInline = MathArrays.linearCombination(a[0], b[0],
+                                                                             a[1], b[1],
+                                                                             a[2], b[2]);
+        final DerivativeStructure abSumArray = MathArrays.linearCombination(a, b);
+
+        Assert.assertEquals(abSumInline.getValue(), abSumArray.getValue(), 0);
+        Assert.assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
+        Assert.assertEquals(b[0].getValue(), abSumInline.getPartialDerivative(1, 0, 0, 0,
0, 0), 1.0e-15);
+        Assert.assertEquals(b[1].getValue(), abSumInline.getPartialDerivative(0, 1, 0, 0,
0, 0), 1.0e-15);
+        Assert.assertEquals(b[2].getValue(), abSumInline.getPartialDerivative(0, 0, 1, 0,
0, 0), 1.0e-15);
+        Assert.assertEquals(a[0].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 1,
0, 0), 1.0e-15);
+        Assert.assertEquals(a[1].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 0,
1, 0), 1.0e-15);
+        Assert.assertEquals(a[2].getValue(), abSumInline.getPartialDerivative(0, 0, 0, 0,
0, 1), 1.0e-15);
+
+    }
+
+    @Test
+    public void testLinearCombination1DoubleDS() {
+        final double[] a = new double[] {
+            -1321008684645961.0 / 268435456.0,
+            -5774608829631843.0 / 268435456.0,
+            -7645843051051357.0 / 8589934592.0
+        };
+        final DerivativeStructure[] b = new DerivativeStructure[] {
+            new DerivativeStructure(3, 1, 0, -5712344449280879.0 / 2097152.0),
+            new DerivativeStructure(3, 1, 1, -4550117129121957.0 / 2097152.0),
+            new DerivativeStructure(3, 1, 2, 8846951984510141.0 / 131072.0)
+        };
+
+        final DerivativeStructure abSumInline = MathArrays.linearCombination(a[0], b[0],
+                                                                             a[1], b[1],
+                                                                             a[2], b[2]);
+        final DerivativeStructure abSumArray = MathArrays.linearCombination(a, b);
+
+        Assert.assertEquals(abSumInline.getValue(), abSumArray.getValue(), 0);
+        Assert.assertEquals(-1.8551294182586248737720779899, abSumInline.getValue(), 1.0e-15);
+        Assert.assertEquals(a[0], abSumInline.getPartialDerivative(1, 0, 0), 1.0e-15);
+        Assert.assertEquals(a[1], abSumInline.getPartialDerivative(0, 1, 0), 1.0e-15);
+        Assert.assertEquals(a[2], abSumInline.getPartialDerivative(0, 0, 1), 1.0e-15);
+
+    }
+
+    @Test
+    public void testLinearCombination2DSDS() {
+        // we compare accurate versus naive dot product implementations
+        // on regular vectors (i.e. not extreme cases like in the previous test)
+        Well1024a random = new Well1024a(0xc6af886975069f11l);
+
+        for (int i = 0; i < 10000; ++i) {
+            final DerivativeStructure[] u = new DerivativeStructure[4];
+            final DerivativeStructure[] v = new DerivativeStructure[4];
+            for (int j = 0; j < u.length; ++j) {
+                u[j] = new DerivativeStructure(u.length, 1, j, 1e17 * random.nextDouble());
+                v[j] = new DerivativeStructure(u.length, 1, 1e17 * random.nextDouble());
+            }
+
+            DerivativeStructure lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1]);
+            double ref = u[0].getValue() * v[0].getValue() +
+                         u[1].getValue() * v[1].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15
* FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15
* FastMath.abs(v[1].getValue()));
+
+            lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
+            ref = u[0].getValue() * v[0].getValue() +
+                  u[1].getValue() * v[1].getValue() +
+                  u[2].getValue() * v[2].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15
* FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15
* FastMath.abs(v[1].getValue()));
+            Assert.assertEquals(v[2].getValue(), lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15
* FastMath.abs(v[2].getValue()));
+
+            lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3],
v[3]);
+            ref = u[0].getValue() * v[0].getValue() +
+                  u[1].getValue() * v[1].getValue() +
+                  u[2].getValue() * v[2].getValue() +
+                  u[3].getValue() * v[3].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(v[0].getValue(), lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15
* FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(v[1].getValue(), lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15
* FastMath.abs(v[1].getValue()));
+            Assert.assertEquals(v[2].getValue(), lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15
* FastMath.abs(v[2].getValue()));
+            Assert.assertEquals(v[3].getValue(), lin.getPartialDerivative(0, 0, 0, 1), 1.0e-15
* FastMath.abs(v[3].getValue()));
+
+        }
+    }
+
+    @Test
+    public void testLinearCombination2DoubleDS() {
+        // we compare accurate versus naive dot product implementations
+        // on regular vectors (i.e. not extreme cases like in the previous test)
+        Well1024a random = new Well1024a(0xc6af886975069f11l);
+
+        for (int i = 0; i < 10000; ++i) {
+            final double[] u = new double[4];
+            final DerivativeStructure[] v = new DerivativeStructure[4];
+            for (int j = 0; j < u.length; ++j) {
+                u[j] = 1e17 * random.nextDouble();
+                v[j] = new DerivativeStructure(u.length, 1, j, 1e17 * random.nextDouble());
+            }
+
+            DerivativeStructure lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1]);
+            double ref = u[0] * v[0].getValue() +
+                         u[1] * v[1].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
+
+            lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1], u[2], v[2]);
+            ref = u[0] * v[0].getValue() +
+                  u[1] * v[1].getValue() +
+                  u[2] * v[2].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
+            Assert.assertEquals(u[2], lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
+
+            lin = MathArrays.linearCombination(u[0], v[0], u[1], v[1], u[2], v[2], u[3],
v[3]);
+            ref = u[0] * v[0].getValue() +
+                  u[1] * v[1].getValue() +
+                  u[2] * v[2].getValue() +
+                  u[3] * v[3].getValue();
+            Assert.assertEquals(ref, lin.getValue(), 1.0e-15 * FastMath.abs(ref));
+            Assert.assertEquals(u[0], lin.getPartialDerivative(1, 0, 0, 0), 1.0e-15 * FastMath.abs(v[0].getValue()));
+            Assert.assertEquals(u[1], lin.getPartialDerivative(0, 1, 0, 0), 1.0e-15 * FastMath.abs(v[1].getValue()));
+            Assert.assertEquals(u[2], lin.getPartialDerivative(0, 0, 1, 0), 1.0e-15 * FastMath.abs(v[2].getValue()));
+            Assert.assertEquals(u[3], lin.getPartialDerivative(0, 0, 0, 1), 1.0e-15 * FastMath.abs(v[3].getValue()));
+
+        }
+    }
+
+    @Test
     public void testArrayEquals() {
         Assert.assertFalse(MathArrays.equals(new double[] { 1d }, null));
         Assert.assertFalse(MathArrays.equals(null, new double[] { 1d }));



Mime
View raw message