Fix a variadic evaluation bug in AutoDiff.

Thanks to Julien Michot for reporting.

Change-Id: I322cd177e85c18ba3fbee56149696d4140f79c68
diff --git a/include/ceres/internal/autodiff.h b/include/ceres/internal/autodiff.h
index 581e881..3497a90 100644
--- a/include/ceres/internal/autodiff.h
+++ b/include/ceres/internal/autodiff.h
@@ -390,7 +390,7 @@
         x.get() + jet8,
         x.get() + jet9,
     };
-    JetT *output = x.get() + jet6;
+    JetT* output = x.get() + jet9;
 
 #define CERES_MAKE_1ST_ORDER_PERTURBATION(i) \
     if (N ## i) { \
diff --git a/internal/ceres/autodiff_test.cc b/internal/ceres/autodiff_test.cc
index d0bf97a..1c56c22 100644
--- a/internal/ceres/autodiff_test.cc
+++ b/internal/ceres/autodiff_test.cc
@@ -377,6 +377,276 @@
   }
 }
 
+struct Residual1Param {
+  template <typename T>
+  bool operator()(const T* x0, T* y) const {
+    y[0] = *x0;
+    return true;
+  }
+};
+
+struct Residual2Param {
+  template <typename T>
+  bool operator()(const T* x0, const T* x1, T* y) const {
+    y[0] = *x0 + pow(*x1, 2);
+    return true;
+  }
+};
+
+struct Residual3Param {
+  template <typename T>
+  bool operator()(const T* x0, const T* x1, const T* x2, T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3);
+    return true;
+  }
+};
+
+struct Residual4Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4);
+    return true;
+  }
+};
+
+struct Residual5Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5);
+    return true;
+  }
+};
+
+struct Residual6Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  const T* x5,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
+        pow(*x5, 6);
+    return true;
+  }
+};
+
+struct Residual7Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  const T* x5,
+                  const T* x6,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
+        pow(*x5, 6) + pow(*x6, 7);
+    return true;
+  }
+};
+
+struct Residual8Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  const T* x5,
+                  const T* x6,
+                  const T* x7,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
+        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8);
+    return true;
+  }
+};
+
+struct Residual9Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  const T* x5,
+                  const T* x6,
+                  const T* x7,
+                  const T* x8,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
+        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9);
+    return true;
+  }
+};
+
+struct Residual10Param {
+  template <typename T>
+  bool operator()(const T* x0,
+                  const T* x1,
+                  const T* x2,
+                  const T* x3,
+                  const T* x4,
+                  const T* x5,
+                  const T* x6,
+                  const T* x7,
+                  const T* x8,
+                  const T* x9,
+                  T* y) const {
+    y[0] = *x0 + pow(*x1, 2) + pow(*x2, 3) + pow(*x3, 4) + pow(*x4, 5) +
+        pow(*x5, 6) + pow(*x6, 7) + pow(*x7, 8) + pow(*x8, 9) + pow(*x9, 10);
+    return true;
+  }
+};
+
+TEST(AutoDiff, VariadicAutoDiff) {
+  double x[10];
+  double residual = 0;
+  double* parameters[10];
+  double jacobian_values[10];
+  double* jacobians[10];
+
+  for (int i = 0; i < 10; ++i) {
+    x[i] = 2.0;
+    parameters[i] = x + i;
+    jacobians[i] = jacobian_values + i;
+  }
+
+  {
+    Residual1Param functor;
+    int num_variables = 1;
+    EXPECT_TRUE((AutoDiff<Residual1Param, double, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual2Param functor;
+    int num_variables = 2;
+    EXPECT_TRUE((AutoDiff<Residual2Param, double, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual3Param functor;
+    int num_variables = 3;
+    EXPECT_TRUE((AutoDiff<Residual3Param, double, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual4Param functor;
+    int num_variables = 4;
+    EXPECT_TRUE((AutoDiff<Residual4Param, double, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual5Param functor;
+    int num_variables = 5;
+    EXPECT_TRUE((AutoDiff<Residual5Param, double, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual6Param functor;
+    int num_variables = 6;
+    EXPECT_TRUE((AutoDiff<Residual6Param,
+                 double,
+                 1, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual7Param functor;
+    int num_variables = 7;
+    EXPECT_TRUE((AutoDiff<Residual7Param,
+                 double,
+                 1, 1, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual8Param functor;
+    int num_variables = 8;
+    EXPECT_TRUE((AutoDiff<
+                 Residual8Param,
+                 double, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual9Param functor;
+    int num_variables = 9;
+    EXPECT_TRUE((AutoDiff<
+                 Residual9Param,
+                 double,
+                 1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+
+  {
+    Residual10Param functor;
+    int num_variables = 10;
+    EXPECT_TRUE((AutoDiff<
+                 Residual10Param,
+                 double,
+                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1>::Differentiate(
+                     functor, parameters, 1, &residual, jacobians)));
+    EXPECT_EQ(residual, pow(2, num_variables + 1) - 2);
+    for (int i = 0; i < num_variables; ++i) {
+      EXPECT_EQ(jacobian_values[i], (i + 1) * pow(2, i));
+    }
+  }
+}
+
 // This is fragile test that triggers the alignment bug on
 // i686-apple-darwin10-llvm-g++-4.2 (GCC) 4.2.1. It is quite possible,
 // that other combinations of operating system + compiler will