10ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Ceres Solver - A fast non-linear least squares minimizer
20ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
30ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// http://code.google.com/p/ceres-solver/
40ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
50ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Redistribution and use in source and binary forms, with or without
60ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// modification, are permitted provided that the following conditions are met:
70ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
80ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions of source code must retain the above copyright notice,
90ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer.
100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Redistributions in binary form must reproduce the above copyright notice,
110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   this list of conditions and the following disclaimer in the documentation
120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   and/or other materials provided with the distribution.
130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// * Neither the name of Google Inc. nor the names of its contributors may be
140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   used to endorse or promote products derived from this software without
150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   specific prior written permission.
160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// POSSIBILITY OF SUCH DAMAGE.
280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Author: keir@google.com (Keir Mierle)
300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/internal/autodiff.h"
320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "gtest/gtest.h"
340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#include "ceres/random.h"
350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace ceres {
370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongnamespace internal {
380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate <typename T> inline
400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongT &RowMajorAccess(T *base, int rows, int cols, int i, int j) {
410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return base[cols * i + j];
420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Do (symmetric) finite differencing using the given function object 'b' of
450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// type 'B' and scalar type 'T' with step size 'del'.
460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// The type B should have a signature
480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//   bool operator()(T const *, T *) const;
500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// which maps a vector of parameters to a vector of outputs.
520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate <typename B, typename T, int M, int N> inline
530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongbool SymmetricDiff(const B& b,
540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                   const T par[N],
550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                   T del,           // step size.
560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                   T fun[M],
570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                   T jac[M * N]) {  // row-major.
580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  if (!b(par, fun)) {
590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Temporary parameter vector.
630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  T tmp_par[N];
640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int j = 0; j < N; ++j) {
650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    tmp_par[j] = par[j];
660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // For each dimension, we do one forward step and one backward step in
690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // parameter space, and store the output vector vectors in these vectors.
700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  T fwd_fun[M];
710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  T bwd_fun[M];
720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int j = 0; j < N; ++j) {
740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Forward step.
750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    tmp_par[j] = par[j] + del;
760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (!b(tmp_par, fwd_fun)) {
770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return false;
780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Backward step.
810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    tmp_par[j] = par[j] - del;
820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (!b(tmp_par, bwd_fun)) {
830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return false;
840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Symmetric differencing:
870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    //   f'(a) = (f(a + h) - f(a - h)) / (2 h)
880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < M; ++i) {
890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      RowMajorAccess(jac, M, N, i, j) =
900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong          (fwd_fun[i] - bwd_fun[i]) / (T(2) * del);
910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Restore our temporary vector.
940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    tmp_par[j] = par[j];
950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  return true;
980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongtemplate <typename A> inline
1010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongvoid QuaternionToScaledRotation(A const q[4], A R[3 * 3]) {
1020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Make convenient names for elements of q.
1030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A a = q[0];
1040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A b = q[1];
1050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A c = q[2];
1060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A d = q[3];
1070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // This is not to eliminate common sub-expression, but to
1080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // make the lines shorter so that they fit in 80 columns!
1090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A aa = a*a;
1100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A ab = a*b;
1110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A ac = a*c;
1120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A ad = a*d;
1130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A bb = b*b;
1140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A bc = b*c;
1150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A bd = b*d;
1160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A cc = c*c;
1170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A cd = c*d;
1180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  A dd = d*d;
1190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#define R(i, j) RowMajorAccess(R, 3, 3, (i), (j))
1200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  R(0, 0) =  aa+bb-cc-dd; R(0, 1) = A(2)*(bc-ad); R(0, 2) = A(2)*(ac+bd);  // NOLINT
1210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  R(1, 0) = A(2)*(ad+bc); R(1, 1) =  aa-bb+cc-dd; R(1, 2) = A(2)*(cd-ab);  // NOLINT
1220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  R(2, 0) = A(2)*(bd-ac); R(2, 1) = A(2)*(ab+cd); R(2, 2) =  aa-bb-cc+dd;  // NOLINT
1230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong#undef R
1240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
1250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// A structure for projecting a 3x4 camera matrix and a
1270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// homogeneous 3D point, to a 2D inhomogeneous point.
1280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongstruct Projective {
1290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Function that takes P and X as separate vectors:
1300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //   P, X -> x
1310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  template <typename A>
1320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool operator()(A const P[12], A const X[4], A x[2]) const {
1330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    A PX[3];
1340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 3; ++i) {
1350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      PX[i] = RowMajorAccess(P, 3, 4, i, 0) * X[0] +
1360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong              RowMajorAccess(P, 3, 4, i, 1) * X[1] +
1370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong              RowMajorAccess(P, 3, 4, i, 2) * X[2] +
1380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong              RowMajorAccess(P, 3, 4, i, 3) * X[3];
1390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
1400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    if (PX[2] != 0.0) {
1410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      x[0] = PX[0] / PX[2];
1420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      x[1] = PX[1] / PX[2];
1430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      return true;
1440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
1450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return false;
1460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Version that takes P and X packed in one vector:
1490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //
1500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //   (P, X) -> x
1510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //
1520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  template <typename A>
1530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool operator()(A const P_X[12 + 4], A x[2]) const {
1540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return operator()(P_X + 0, P_X + 12, x);
1550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong};
1570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Test projective camera model projector.
1590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(AutoDiff, ProjectiveCameraModel) {
1600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  srand(5);
1610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const tol = 1e-10;  // floating-point tolerance.
1620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const del = 1e-4;   // finite-difference step.
1630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const err = 1e-6;   // finite-difference tolerance.
1640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Projective b;
1660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Make random P and X, in a single vector.
1680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double PX[12 + 4];
1690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 12 + 4; ++i) {
1700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    PX[i] = RandDouble();
1710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Handy names for the P and X parts.
1740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *P = PX + 0;
1750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *X = PX + 12;
1760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Apply the mapping, to get image point b_x.
1780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double b_x[2];
1790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  b(P, X, b_x);
1800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Use finite differencing to estimate the Jacobian.
1820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double fd_x[2];
1830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double fd_J[2 * (12 + 4)];
1840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_TRUE((SymmetricDiff<Projective, double, 2, 12 + 4>(b, PX, del,
1850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                                                            fd_x, fd_J)));
1860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 2; ++i) {
1880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_EQ(fd_x[i], b_x[i]);
1890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
1900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
1910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Use automatic differentiation to compute the Jacobian.
1920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double ad_x1[2];
1930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double J_PX[2 * (12 + 4)];
1940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  {
1950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double *parameters[] = { PX };
1960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double *jacobians[] = { J_PX };
1970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_TRUE((AutoDiff<Projective, double, 12 + 4>::Differentiate(
1980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        b, parameters, 2, ad_x1, jacobians)));
1990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 2; ++i) {
2010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ASSERT_NEAR(ad_x1[i], b_x[i], tol);
2020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Use automatic differentiation (again), with two arguments.
2060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  {
2070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double ad_x2[2];
2080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double J_P[2 * 12];
2090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double J_X[2 * 4];
2100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double *parameters[] = { P, X };
2110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    double *jacobians[] = { J_P, J_X };
2120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_TRUE((AutoDiff<Projective, double, 12, 4>::Differentiate(
2130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        b, parameters, 2, ad_x2, jacobians)));
2140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 2; ++i) {
2160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ASSERT_NEAR(ad_x2[i], b_x[i], tol);
2170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Now compare the jacobians we got.
2200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 2; ++i) {
2210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      for (int j = 0; j < 12 + 4; ++j) {
2220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        ASSERT_NEAR(J_PX[(12 + 4) * i + j], fd_J[(12 + 4) * i + j], err);
2230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      for (int j = 0; j < 12; ++j) {
2260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        ASSERT_NEAR(J_PX[(12 + 4) * i + j], J_P[12 * i + j], tol);
2270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      for (int j = 0; j < 4; ++j) {
2290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        ASSERT_NEAR(J_PX[(12 + 4) * i + 12 + j], J_X[4 * i + j], tol);
2300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
2340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// Object to implement the projection by a calibrated camera.
2360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongstruct Metric {
2370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // The mapping is
2380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //
2390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //   q, c, X -> x = dehomg(R(q) (X - c))
2400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //
2410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // where q is a quaternion and c is the center of projection.
2420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  //
2430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // This function takes three input vectors.
2440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  template <typename A>
2450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool operator()(A const q[4], A const c[3], A const X[3], A x[2]) const {
2460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    A R[3 * 3];
2470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    QuaternionToScaledRotation(q, R);
2480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Convert the quaternion mapping all the way to projective matrix.
2500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    A P[3 * 4];
2510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Set P(:, 1:3) = R
2530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 3; ++i) {
2540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      for (int j = 0; j < 3; ++j) {
2550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        RowMajorAccess(P, 3, 4, i, j) = RowMajorAccess(R, 3, 3, i, j);
2560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      }
2570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Set P(:, 4) = - R c
2600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < 3; ++i) {
2610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      RowMajorAccess(P, 3, 4, i, 3) =
2620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        - (RowMajorAccess(R, 3, 3, i, 0) * c[0] +
2630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong           RowMajorAccess(R, 3, 3, i, 1) * c[1] +
2640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong           RowMajorAccess(R, 3, 3, i, 2) * c[2]);
2650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
2660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    A X1[4] = { X[0], X[1], X[2], A(1) };
2680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    Projective p;
2690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return p(P, X1, x);
2700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // A version that takes a single vector.
2730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  template <typename A>
2740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool operator()(A const q_c_X[4 + 3 + 3], A x[2]) const {
2750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return operator()(q_c_X, q_c_X + 4, q_c_X + 4 + 3, x);
2760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
2770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong};
2780ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2790ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// This test is similar in structure to the previous one.
2800ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(AutoDiff, Metric) {
2810ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  srand(5);
2820ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const tol = 1e-10;  // floating-point tolerance.
2830ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const del = 1e-4;   // finite-difference step.
2840ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double const err = 1e-5;   // finite-difference tolerance.
2850ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2860ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  Metric b;
2870ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2880ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Make random parameter vector.
2890ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double qcX[4 + 3 + 3];
2900ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 4 + 3 + 3; ++i)
2910ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    qcX[i] = RandDouble();
2920ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2930ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Handy names.
2940ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *q = qcX;
2950ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *c = qcX + 4;
2960ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *X = qcX + 4 + 3;
2970ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
2980ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Compute projection, b_x.
2990ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double b_x[2];
3000ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_TRUE(b(q, c, X, b_x));
3010ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3020ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Finite differencing estimate of Jacobian.
3030ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double fd_x[2];
3040ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double fd_J[2 * (4 + 3 + 3)];
3050ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_TRUE((SymmetricDiff<Metric, double, 2, 4 + 3 + 3>(b, qcX, del,
3060ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong                                                           fd_x, fd_J)));
3070ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3080ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 2; ++i) {
3090ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_NEAR(fd_x[i], b_x[i], tol);
3100ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
3110ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3120ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Automatic differentiation.
3130ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double ad_x[2];
3140ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double J_q[2 * 4];
3150ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double J_c[2 * 3];
3160ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double J_X[2 * 3];
3170ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *parameters[] = { q, c, X };
3180ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *jacobians[] = { J_q, J_c, J_X };
3190ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  ASSERT_TRUE((AutoDiff<Metric, double, 4, 3, 3>::Differentiate(
3200ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      b, parameters, 2, ad_x, jacobians)));
3210ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3220ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 2; ++i) {
3230ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_NEAR(ad_x[i], b_x[i], tol);
3240ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
3250ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3260ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Compare the pieces.
3270ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int i = 0; i < 2; ++i) {
3280ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int j = 0; j < 4; ++j) {
3290ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ASSERT_NEAR(J_q[4 * i + j], fd_J[(4 + 3 + 3) * i + j], err);
3300ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
3310ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int j = 0; j < 3; ++j) {
3320ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ASSERT_NEAR(J_c[3 * i + j], fd_J[(4 + 3 + 3) * i + j + 4], err);
3330ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
3340ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int j = 0; j < 3; ++j) {
3350ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      ASSERT_NEAR(J_X[3 * i + j], fd_J[(4 + 3 + 3) * i + j + 4 + 3], err);
3360ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
3370ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
3380ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
3390ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3400ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kongstruct VaryingResidualFunctor {
3410ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  template <typename T>
3420ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  bool operator()(const T x[2], T* y) const {
3430ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < num_residuals; ++i) {
3440ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      y[i] = T(i) * x[0] * x[1] * x[1];
3450ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
3460ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    return true;
3470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
3480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  int num_residuals;
3500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong};
3510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(AutoDiff, VaryingNumberOfResidualsForOneCostFunctorType) {
3530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double x[2] = { 1.0, 5.5 };
3540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *parameters[] = { x };
3550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  const int kMaxResiduals = 10;
3560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double J_x[2 * kMaxResiduals];
3570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double residuals[kMaxResiduals];
3580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  double *jacobians[] = { J_x };
3590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Use a single functor, but tweak it to produce different numbers of
3610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // residuals.
3620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  VaryingResidualFunctor functor;
3630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  for (int num_residuals = 1; num_residuals < kMaxResiduals; ++num_residuals) {
3650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Tweak the number of residuals to produce.
3660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    functor.num_residuals = num_residuals;
3670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    // Run autodiff with the new number of residuals.
3690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    ASSERT_TRUE((AutoDiff<VaryingResidualFunctor, double, 2>::Differentiate(
3700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong        functor, parameters, num_residuals, residuals, jacobians)));
3710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
3720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    const double kTolerance = 1e-14;
3730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    for (int i = 0; i < num_residuals; ++i) {
3740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong      EXPECT_NEAR(J_x[2 * i + 0], i * x[1] * x[1], kTolerance) << "i: " << i;
3751d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_NEAR(J_x[2 * i + 1], 2 * i * x[0] * x[1], kTolerance)
3761d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling          << "i: " << i;
3771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
3781d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
3791d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling}
3801d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
3811d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual1Param {
3821d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
3831d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0, T* y) const {
3841d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0;
3851d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
3861d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
3871d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
3881d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
3891d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual2Param {
3901d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
3911d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0, const T* x1, T* y) const {
3921d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2);
3931d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
3941d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
3951d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
3961d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
3971d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual3Param {
3981d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
3991d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0, const T* x1, const T* x2, T* y) const {
4001d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3);
4011d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4021d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4031d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4041d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4051d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual4Param {
4061d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4071d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4081d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4091d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4101d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4121d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4);
4131d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4141d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4151d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4161d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4171d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual5Param {
4181d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4191d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4201d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4211d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4221d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4231d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
4241d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4251d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5);
4261d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4271d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4281d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4291d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4301d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual6Param {
4311d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4341d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4351d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4361d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
4371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x5,
4381d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4391d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
4401d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        pow(*x5, 6);
4411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4421d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4431d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4441d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4451d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual7Param {
4461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4481d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
4521d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x5,
4531d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x6,
4541d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4551d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
4561d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        pow(*x5, 6) + pow(*x6, 7);
4571d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4581d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4591d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4601d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4611d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual8Param {
4621d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4631d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4651d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4661d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4671d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
4681d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x5,
4691d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x6,
4701d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x7,
4711d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4721d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
4731d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8);
4741d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4751d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4761d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4781d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual9Param {
4791d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4801d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4811d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
4821d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
4831d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
4841d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
4851d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x5,
4861d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x6,
4871d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x7,
4881d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x8,
4891d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
4901d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
4911d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9);
4921d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
4931d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
4941d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
4951d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
4961d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberlingstruct Residual10Param {
4971d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  template <typename T>
4981d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  bool operator()(const T* x0,
4991d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x1,
5001d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x2,
5011d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x3,
5021d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x4,
5031d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x5,
5041d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x6,
5051d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x7,
5061d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x8,
5071d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  const T* x9,
5081d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                  T* y) const {
5091d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
5101d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9) + pow(*x9, 10);
5111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    return true;
5121d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5131d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling};
5141d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5151d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha HaeberlingTEST(AutoDiff, VariadicAutoDiff) {
5161d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double x[10];
5171d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double residual = 0;
5181d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double* parameters[10];
5191d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double jacobian_values[10];
5201d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  double* jacobians[10];
5211d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5221d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  for (int i = 0; i < 10; ++i) {
5231d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    x[i] = 2.0;
5241d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    parameters[i] = x + i;
5251d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    jacobians[i] = jacobian_values + i;
5261d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5271d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5281d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5291d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual1Param functor;
5301d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 1;
5311d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual1Param, double, 1>::Differentiate(
5321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5341d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5351d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5361d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5381d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5391d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5401d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual2Param functor;
5411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 2;
5421d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual2Param, double, 1, 1>::Differentiate(
5431d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5441d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5451d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5471d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5481d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5491d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5501d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5511d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual3Param functor;
5521d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 3;
5531d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual3Param, double, 1, 1, 1>::Differentiate(
5541d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5551d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5561d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5571d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5581d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5591d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5601d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5611d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5621d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual4Param functor;
5631d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 4;
5641d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual4Param, double, 1, 1, 1, 1>::Differentiate(
5651d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5661d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5671d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5681d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5691d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5701d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5711d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5721d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5731d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual5Param functor;
5741d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 5;
5751d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual5Param, double, 1, 1, 1, 1, 1>::Differentiate(
5761d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5771d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5781d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5791d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5801d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5811d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5821d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5831d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5841d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual6Param functor;
5851d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 6;
5861d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual6Param,
5871d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 double,
5881d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 1, 1, 1, 1, 1, 1>::Differentiate(
5891d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
5901d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
5911d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
5921d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
5931d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
5941d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
5951d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
5961d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
5971d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual7Param functor;
5981d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 7;
5991d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<Residual7Param,
6001d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 double,
6011d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 1, 1, 1, 1, 1, 1, 1>::Differentiate(
6021d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
6031d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
6041d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
6051d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
6061d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
6071d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
6081d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
6091d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
6101d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual8Param functor;
6111d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 8;
6121d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<
6131d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 Residual8Param,
6141d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 double, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
6151d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
6161d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
6171d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
6181d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
6191d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
6201d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
6211d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
6221d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
6231d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual9Param functor;
6241d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 9;
6251d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<
6261d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 Residual9Param,
6271d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 double,
6281d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
6291d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
6301d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
6311d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
6321d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
6331d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    }
6341d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  }
6351d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling
6361d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling  {
6371d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    Residual10Param functor;
6381d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    int num_variables = 10;
6391d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_TRUE((AutoDiff<
6401d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 Residual10Param,
6411d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 double,
6421d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
6431d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling                     functor, parameters, 1, &residual, jacobians)));
6441d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
6451d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling    for (int i = 0; i < num_variables; ++i) {
6461d2624a10e2c559f8ba9ef89eaa30832c0a83a96Sascha Haeberling      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
6470ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong    }
6480ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  }
6490ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
6500ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
6510ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// This is fragile test that triggers the alignment bug on
6520ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// i686-apple-darwin10-llvm-g++-4.2 (GCC) 4.2.1. It is quite possible,
6530ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// that other combinations of operating system + compiler will
6540ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// re-arrange the operations in this test.
6550ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong//
6560ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// But this is the best (and only) way we know of to trigger this
6570ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// problem for now. A more robust solution that guarantees the
6580ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// alignment of Eigen types used for automatic differentiation would
6590ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong// be nice.
6600ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus KongTEST(AutoDiff, AlignedAllocationTest) {
6610ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // This int is needed to allocate 16 bits on the stack, so that the
6620ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // next allocation is not aligned by default.
6630ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  char y = 0;
6640ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
6650ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // This is needed to prevent the compiler from optimizing y out of
6660ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // this function.
6670ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  y += 1;
6680ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
6690ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  typedef Jet<double, 2> JetT;
6700ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  FixedArray<JetT, (256 * 7) / sizeof(JetT)> x(3);
6710ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
6720ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  // Need this to makes sure that x does not get optimized out.
6730ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong  x[0] = x[0] + JetT(1.0);
6740ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}
6750ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong
6760ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace internal
6770ae28bd5885b5daa526898fcf7c323dc2c3e1963Angus Kong}  // namespace ceres
678