|  | @@ -37,7 +37,7 @@ namespace ceres {
 | 
	
		
			
				|  |  |  namespace internal {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  template <typename T> inline
 | 
	
		
			
				|  |  | -T &RowMajor(T *base, int rows, int cols, int i, int j) {
 | 
	
		
			
				|  |  | +T &RowMajorAccess(T *base, int rows, int cols, int i, int j) {
 | 
	
		
			
				|  |  |    return base[cols * i + j];
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -86,7 +86,7 @@ bool SymmetricDiff(const B& b,
 | 
	
		
			
				|  |  |      // Symmetric differencing:
 | 
	
		
			
				|  |  |      //   f'(a) = (f(a + h) - f(a - h)) / (2 h)
 | 
	
		
			
				|  |  |      for (int i = 0; i < M; ++i) {
 | 
	
		
			
				|  |  | -      RowMajor(jac, M, N, i, j) =
 | 
	
		
			
				|  |  | +      RowMajorAccess(jac, M, N, i, j) =
 | 
	
		
			
				|  |  |            (fwd_fun[i] - bwd_fun[i]) / (T(2) * del);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -116,7 +116,7 @@ void QuaternionToScaledRotation(A const q[4], A R[3 * 3]) {
 | 
	
		
			
				|  |  |    A cc = c*c;
 | 
	
		
			
				|  |  |    A cd = c*d;
 | 
	
		
			
				|  |  |    A dd = d*d;
 | 
	
		
			
				|  |  | -#define R(i, j) RowMajor(R, 3, 3, (i), (j))
 | 
	
		
			
				|  |  | +#define R(i, j) RowMajorAccess(R, 3, 3, (i), (j))
 | 
	
		
			
				|  |  |    R(0, 0) =  aa+bb-cc-dd; R(0, 1) = A(2)*(bc-ad); R(0, 2) = A(2)*(ac+bd);  // NOLINT
 | 
	
		
			
				|  |  |    R(1, 0) = A(2)*(ad+bc); R(1, 1) =  aa-bb+cc-dd; R(1, 2) = A(2)*(cd-ab);  // NOLINT
 | 
	
		
			
				|  |  |    R(2, 0) = A(2)*(bd-ac); R(2, 1) = A(2)*(ab+cd); R(2, 2) =  aa-bb-cc+dd;  // NOLINT
 | 
	
	
		
			
				|  | @@ -132,10 +132,10 @@ struct Projective {
 | 
	
		
			
				|  |  |    bool operator()(A const P[12], A const X[4], A x[2]) const {
 | 
	
		
			
				|  |  |      A PX[3];
 | 
	
		
			
				|  |  |      for (int i = 0; i < 3; ++i) {
 | 
	
		
			
				|  |  | -      PX[i] = RowMajor(P, 3, 4, i, 0) * X[0] +
 | 
	
		
			
				|  |  | -              RowMajor(P, 3, 4, i, 1) * X[1] +
 | 
	
		
			
				|  |  | -              RowMajor(P, 3, 4, i, 2) * X[2] +
 | 
	
		
			
				|  |  | -              RowMajor(P, 3, 4, i, 3) * X[3];
 | 
	
		
			
				|  |  | +      PX[i] = RowMajorAccess(P, 3, 4, i, 0) * X[0] +
 | 
	
		
			
				|  |  | +              RowMajorAccess(P, 3, 4, i, 1) * X[1] +
 | 
	
		
			
				|  |  | +              RowMajorAccess(P, 3, 4, i, 2) * X[2] +
 | 
	
		
			
				|  |  | +              RowMajorAccess(P, 3, 4, i, 3) * X[3];
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      if (PX[2] != 0.0) {
 | 
	
		
			
				|  |  |        x[0] = PX[0] / PX[2];
 | 
	
	
		
			
				|  | @@ -194,8 +194,8 @@ TEST(AutoDiff, ProjectiveCameraModel) {
 | 
	
		
			
				|  |  |    {
 | 
	
		
			
				|  |  |      double *parameters[] = { PX };
 | 
	
		
			
				|  |  |      double *jacobians[] = { J_PX };
 | 
	
		
			
				|  |  | -    ASSERT_TRUE((AutoDiff<Projective, double, 2, 12 + 4>::Differentiate(
 | 
	
		
			
				|  |  | -        b, parameters, ad_x1, jacobians)));
 | 
	
		
			
				|  |  | +    ASSERT_TRUE((AutoDiff<Projective, double, 12 + 4>::Differentiate(
 | 
	
		
			
				|  |  | +        b, parameters, 2, ad_x1, jacobians)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for (int i = 0; i < 2; ++i) {
 | 
	
		
			
				|  |  |        ASSERT_NEAR(ad_x1[i], b_x[i], tol);
 | 
	
	
		
			
				|  | @@ -209,8 +209,8 @@ TEST(AutoDiff, ProjectiveCameraModel) {
 | 
	
		
			
				|  |  |      double J_X[2 * 4];
 | 
	
		
			
				|  |  |      double *parameters[] = { P, X };
 | 
	
		
			
				|  |  |      double *jacobians[] = { J_P, J_X };
 | 
	
		
			
				|  |  | -    ASSERT_TRUE((AutoDiff<Projective, double, 2, 12, 4>::Differentiate(
 | 
	
		
			
				|  |  | -        b, parameters, ad_x2, jacobians)));
 | 
	
		
			
				|  |  | +    ASSERT_TRUE((AutoDiff<Projective, double, 12, 4>::Differentiate(
 | 
	
		
			
				|  |  | +        b, parameters, 2, ad_x2, jacobians)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for (int i = 0; i < 2; ++i) {
 | 
	
		
			
				|  |  |        ASSERT_NEAR(ad_x2[i], b_x[i], tol);
 | 
	
	
		
			
				|  | @@ -252,16 +252,16 @@ struct Metric {
 | 
	
		
			
				|  |  |      // Set P(:, 1:3) = R
 | 
	
		
			
				|  |  |      for (int i = 0; i < 3; ++i) {
 | 
	
		
			
				|  |  |        for (int j = 0; j < 3; ++j) {
 | 
	
		
			
				|  |  | -        RowMajor(P, 3, 4, i, j) = RowMajor(R, 3, 3, i, j);
 | 
	
		
			
				|  |  | +        RowMajorAccess(P, 3, 4, i, j) = RowMajorAccess(R, 3, 3, i, j);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      // Set P(:, 4) = - R c
 | 
	
		
			
				|  |  |      for (int i = 0; i < 3; ++i) {
 | 
	
		
			
				|  |  | -      RowMajor(P, 3, 4, i, 3) =
 | 
	
		
			
				|  |  | -        - (RowMajor(R, 3, 3, i, 0) * c[0] +
 | 
	
		
			
				|  |  | -           RowMajor(R, 3, 3, i, 1) * c[1] +
 | 
	
		
			
				|  |  | -           RowMajor(R, 3, 3, i, 2) * c[2]);
 | 
	
		
			
				|  |  | +      RowMajorAccess(P, 3, 4, i, 3) =
 | 
	
		
			
				|  |  | +        - (RowMajorAccess(R, 3, 3, i, 0) * c[0] +
 | 
	
		
			
				|  |  | +           RowMajorAccess(R, 3, 3, i, 1) * c[1] +
 | 
	
		
			
				|  |  | +           RowMajorAccess(R, 3, 3, i, 2) * c[2]);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      A X1[4] = { X[0], X[1], X[2], A(1) };
 | 
	
	
		
			
				|  | @@ -316,8 +316,8 @@ TEST(AutoDiff, Metric) {
 | 
	
		
			
				|  |  |    double J_X[2 * 3];
 | 
	
		
			
				|  |  |    double *parameters[] = { q, c, X };
 | 
	
		
			
				|  |  |    double *jacobians[] = { J_q, J_c, J_X };
 | 
	
		
			
				|  |  | -  ASSERT_TRUE((AutoDiff<Metric, double, 2, 4, 3, 3>::Differentiate(
 | 
	
		
			
				|  |  | -      b, parameters, ad_x, jacobians)));
 | 
	
		
			
				|  |  | +  ASSERT_TRUE((AutoDiff<Metric, double, 4, 3, 3>::Differentiate(
 | 
	
		
			
				|  |  | +      b, parameters, 2, ad_x, jacobians)));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    for (int i = 0; i < 2; ++i) {
 | 
	
		
			
				|  |  |      ASSERT_NEAR(ad_x[i], b_x[i], tol);
 | 
	
	
		
			
				|  | @@ -337,5 +337,45 @@ TEST(AutoDiff, Metric) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +struct VaryingResidualFunctor {
 | 
	
		
			
				|  |  | +  template <typename T>
 | 
	
		
			
				|  |  | +  bool operator()(const T x[2], T* y) const {
 | 
	
		
			
				|  |  | +    for (int i = 0; i < num_residuals; ++i) {
 | 
	
		
			
				|  |  | +      y[i] = T(i) * x[0] * x[1] * x[1];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  int num_residuals;
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +TEST(AutoDiff, VaryingNumberOfResidualsForOneCostFunctorType) {
 | 
	
		
			
				|  |  | +  double x[2] = { 1.0, 5.5 };
 | 
	
		
			
				|  |  | +  double *parameters[] = { x };
 | 
	
		
			
				|  |  | +  const int kMaxResiduals = 10;
 | 
	
		
			
				|  |  | +  double J_x[2 * kMaxResiduals];
 | 
	
		
			
				|  |  | +  double residuals[kMaxResiduals];
 | 
	
		
			
				|  |  | +  double *jacobians[] = { J_x };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // Use a single functor, but tweak it to produce different numbers of
 | 
	
		
			
				|  |  | +  // residuals.
 | 
	
		
			
				|  |  | +  VaryingResidualFunctor functor;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  for (int num_residuals = 0; num_residuals < kMaxResiduals; ++num_residuals) {
 | 
	
		
			
				|  |  | +    // Tweak the number of residuals to produce.
 | 
	
		
			
				|  |  | +    functor.num_residuals = num_residuals;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Run autodiff with the new number of residuals.
 | 
	
		
			
				|  |  | +    ASSERT_TRUE((AutoDiff<VaryingResidualFunctor, double, 2>::Differentiate(
 | 
	
		
			
				|  |  | +        functor, parameters, num_residuals, residuals, jacobians)));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    const double kTolerance = 1e-14;
 | 
	
		
			
				|  |  | +    for (int i = 0; i < num_residuals; ++i) {
 | 
	
		
			
				|  |  | +      EXPECT_NEAR(J_x[2 * i + 0], i * x[1] * x[1], kTolerance) << "i: " << i;
 | 
	
		
			
				|  |  | +      EXPECT_NEAR(J_x[2 * i + 1], 2 * i * x[0] * x[1], kTolerance) << "i: " << i;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }  // namespace internal
 | 
	
		
			
				|  |  |  }  // namespace ceres
 |