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