Home | History | Annotate | Download | only in ceres
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 2012 Google Inc. All rights reserved.
      3 // http://code.google.com/p/ceres-solver/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are met:
      7 //
      8 // * Redistributions of source code must retain the above copyright notice,
      9 //   this list of conditions and the following disclaimer.
     10 // * Redistributions in binary form must reproduce the above copyright notice,
     11 //   this list of conditions and the following disclaimer in the documentation
     12 //   and/or other materials provided with the distribution.
     13 // * Neither the name of Google Inc. nor the names of its contributors may be
     14 //   used to endorse or promote products derived from this software without
     15 //   specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27 // POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 // Author: thadh (at) gmail.com (Thad Hughes)
     30 //         mierle (at) gmail.com (Keir Mierle)
     31 //         sameeragarwal (at) google.com (Sameer Agarwal)
     32 
     33 #include <cstddef>
     34 
     35 #include "ceres/dynamic_autodiff_cost_function.h"
     36 #include "ceres/internal/scoped_ptr.h"
     37 #include "gtest/gtest.h"
     38 
     39 namespace ceres {
     40 namespace internal {
     41 
     42 // Takes 2 parameter blocks:
     43 //     parameters[0] is size 10.
     44 //     parameters[1] is size 5.
     45 // Emits 21 residuals:
     46 //     A: i - parameters[0][i], for i in [0,10)  -- this is 10 residuals
     47 //     B: parameters[0][i] - i, for i in [0,10)  -- this is another 10.
     48 //     C: sum(parameters[0][i]^2 - 8*parameters[0][i]) + sum(parameters[1][i])
     49 class MyCostFunctor {
     50  public:
     51   template <typename T>
     52   bool operator()(T const* const* parameters, T* residuals) const {
     53     const T* params0 = parameters[0];
     54     int r = 0;
     55     for (int i = 0; i < 10; ++i) {
     56       residuals[r++] = T(i) - params0[i];
     57       residuals[r++] = params0[i] - T(i);
     58     }
     59 
     60     T c_residual(0.0);
     61     for (int i = 0; i < 10; ++i) {
     62       c_residual += pow(params0[i], 2) - T(8) * params0[i];
     63     }
     64 
     65     const T* params1 = parameters[1];
     66     for (int i = 0; i < 5; ++i) {
     67       c_residual += params1[i];
     68     }
     69     residuals[r++] = c_residual;
     70     return true;
     71   }
     72 };
     73 
     74 TEST(DynamicAutodiffCostFunctionTest, TestResiduals) {
     75   vector<double> param_block_0(10, 0.0);
     76   vector<double> param_block_1(5, 0.0);
     77   DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
     78       new MyCostFunctor());
     79   cost_function.AddParameterBlock(param_block_0.size());
     80   cost_function.AddParameterBlock(param_block_1.size());
     81   cost_function.SetNumResiduals(21);
     82 
     83   // Test residual computation.
     84   vector<double> residuals(21, -100000);
     85   vector<double*> parameter_blocks(2);
     86   parameter_blocks[0] = &param_block_0[0];
     87   parameter_blocks[1] = &param_block_1[0];
     88   EXPECT_TRUE(cost_function.Evaluate(&parameter_blocks[0],
     89                                      residuals.data(),
     90                                      NULL));
     91   for (int r = 0; r < 10; ++r) {
     92     EXPECT_EQ(1.0 * r, residuals.at(r * 2));
     93     EXPECT_EQ(-1.0 * r, residuals.at(r * 2 + 1));
     94   }
     95   EXPECT_EQ(0, residuals.at(20));
     96 }
     97 
     98 TEST(DynamicAutodiffCostFunctionTest, TestJacobian) {
     99   // Test the residual counting.
    100   vector<double> param_block_0(10, 0.0);
    101   for (int i = 0; i < 10; ++i) {
    102     param_block_0[i] = 2 * i;
    103   }
    104   vector<double> param_block_1(5, 0.0);
    105   DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
    106       new MyCostFunctor());
    107   cost_function.AddParameterBlock(param_block_0.size());
    108   cost_function.AddParameterBlock(param_block_1.size());
    109   cost_function.SetNumResiduals(21);
    110 
    111   // Prepare the residuals.
    112   vector<double> residuals(21, -100000);
    113 
    114   // Prepare the parameters.
    115   vector<double*> parameter_blocks(2);
    116   parameter_blocks[0] = &param_block_0[0];
    117   parameter_blocks[1] = &param_block_1[0];
    118 
    119   // Prepare the jacobian.
    120   vector<vector<double> > jacobian_vect(2);
    121   jacobian_vect[0].resize(21 * 10, -100000);
    122   jacobian_vect[1].resize(21 * 5, -100000);
    123   vector<double*> jacobian;
    124   jacobian.push_back(jacobian_vect[0].data());
    125   jacobian.push_back(jacobian_vect[1].data());
    126 
    127   // Test jacobian computation.
    128   EXPECT_TRUE(cost_function.Evaluate(parameter_blocks.data(),
    129                                      residuals.data(),
    130                                      jacobian.data()));
    131 
    132   for (int r = 0; r < 10; ++r) {
    133     EXPECT_EQ(-1.0 * r, residuals.at(r * 2));
    134     EXPECT_EQ(+1.0 * r, residuals.at(r * 2 + 1));
    135   }
    136   EXPECT_EQ(420, residuals.at(20));
    137   for (int p = 0; p < 10; ++p) {
    138     // Check "A" Jacobian.
    139     EXPECT_EQ(-1.0, jacobian_vect[0][2*p * 10 + p]);
    140     // Check "B" Jacobian.
    141     EXPECT_EQ(+1.0, jacobian_vect[0][(2*p+1) * 10 + p]);
    142     jacobian_vect[0][2*p * 10 + p] = 0.0;
    143     jacobian_vect[0][(2*p+1) * 10 + p] = 0.0;
    144   }
    145 
    146   // Check "C" Jacobian for first parameter block.
    147   for (int p = 0; p < 10; ++p) {
    148     EXPECT_EQ(4 * p - 8, jacobian_vect[0][20 * 10 + p]);
    149     jacobian_vect[0][20 * 10 + p] = 0.0;
    150   }
    151   for (int i = 0; i < jacobian_vect[0].size(); ++i) {
    152     EXPECT_EQ(0.0, jacobian_vect[0][i]);
    153   }
    154 
    155   // Check "C" Jacobian for second parameter block.
    156   for (int p = 0; p < 5; ++p) {
    157     EXPECT_EQ(1.0, jacobian_vect[1][20 * 5 + p]);
    158     jacobian_vect[1][20 * 5 + p] = 0.0;
    159   }
    160   for (int i = 0; i < jacobian_vect[1].size(); ++i) {
    161     EXPECT_EQ(0.0, jacobian_vect[1][i]);
    162   }
    163 }
    164 
    165 TEST(DynamicAutodiffCostFunctionTest, JacobianWithFirstParameterBlockConstant) {
    166   // Test the residual counting.
    167   vector<double> param_block_0(10, 0.0);
    168   for (int i = 0; i < 10; ++i) {
    169     param_block_0[i] = 2 * i;
    170   }
    171   vector<double> param_block_1(5, 0.0);
    172   DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
    173       new MyCostFunctor());
    174   cost_function.AddParameterBlock(param_block_0.size());
    175   cost_function.AddParameterBlock(param_block_1.size());
    176   cost_function.SetNumResiduals(21);
    177 
    178   // Prepare the residuals.
    179   vector<double> residuals(21, -100000);
    180 
    181   // Prepare the parameters.
    182   vector<double*> parameter_blocks(2);
    183   parameter_blocks[0] = &param_block_0[0];
    184   parameter_blocks[1] = &param_block_1[0];
    185 
    186   // Prepare the jacobian.
    187   vector<vector<double> > jacobian_vect(2);
    188   jacobian_vect[0].resize(21 * 10, -100000);
    189   jacobian_vect[1].resize(21 * 5, -100000);
    190   vector<double*> jacobian;
    191   jacobian.push_back(NULL);
    192   jacobian.push_back(jacobian_vect[1].data());
    193 
    194   // Test jacobian computation.
    195   EXPECT_TRUE(cost_function.Evaluate(parameter_blocks.data(),
    196                                      residuals.data(),
    197                                      jacobian.data()));
    198 
    199   for (int r = 0; r < 10; ++r) {
    200     EXPECT_EQ(-1.0 * r, residuals.at(r * 2));
    201     EXPECT_EQ(+1.0 * r, residuals.at(r * 2 + 1));
    202   }
    203   EXPECT_EQ(420, residuals.at(20));
    204 
    205   // Check "C" Jacobian for second parameter block.
    206   for (int p = 0; p < 5; ++p) {
    207     EXPECT_EQ(1.0, jacobian_vect[1][20 * 5 + p]);
    208     jacobian_vect[1][20 * 5 + p] = 0.0;
    209   }
    210   for (int i = 0; i < jacobian_vect[1].size(); ++i) {
    211     EXPECT_EQ(0.0, jacobian_vect[1][i]);
    212   }
    213 }
    214 
    215 TEST(DynamicAutodiffCostFunctionTest, JacobianWithSecondParameterBlockConstant) {
    216   // Test the residual counting.
    217   vector<double> param_block_0(10, 0.0);
    218   for (int i = 0; i < 10; ++i) {
    219     param_block_0[i] = 2 * i;
    220   }
    221   vector<double> param_block_1(5, 0.0);
    222   DynamicAutoDiffCostFunction<MyCostFunctor, 3> cost_function(
    223       new MyCostFunctor());
    224   cost_function.AddParameterBlock(param_block_0.size());
    225   cost_function.AddParameterBlock(param_block_1.size());
    226   cost_function.SetNumResiduals(21);
    227 
    228   // Prepare the residuals.
    229   vector<double> residuals(21, -100000);
    230 
    231   // Prepare the parameters.
    232   vector<double*> parameter_blocks(2);
    233   parameter_blocks[0] = &param_block_0[0];
    234   parameter_blocks[1] = &param_block_1[0];
    235 
    236   // Prepare the jacobian.
    237   vector<vector<double> > jacobian_vect(2);
    238   jacobian_vect[0].resize(21 * 10, -100000);
    239   jacobian_vect[1].resize(21 * 5, -100000);
    240   vector<double*> jacobian;
    241   jacobian.push_back(jacobian_vect[0].data());
    242   jacobian.push_back(NULL);
    243 
    244   // Test jacobian computation.
    245   EXPECT_TRUE(cost_function.Evaluate(parameter_blocks.data(),
    246                                      residuals.data(),
    247                                      jacobian.data()));
    248 
    249   for (int r = 0; r < 10; ++r) {
    250     EXPECT_EQ(-1.0 * r, residuals.at(r * 2));
    251     EXPECT_EQ(+1.0 * r, residuals.at(r * 2 + 1));
    252   }
    253   EXPECT_EQ(420, residuals.at(20));
    254   for (int p = 0; p < 10; ++p) {
    255     // Check "A" Jacobian.
    256     EXPECT_EQ(-1.0, jacobian_vect[0][2*p * 10 + p]);
    257     // Check "B" Jacobian.
    258     EXPECT_EQ(+1.0, jacobian_vect[0][(2*p+1) * 10 + p]);
    259     jacobian_vect[0][2*p * 10 + p] = 0.0;
    260     jacobian_vect[0][(2*p+1) * 10 + p] = 0.0;
    261   }
    262 
    263   // Check "C" Jacobian for first parameter block.
    264   for (int p = 0; p < 10; ++p) {
    265     EXPECT_EQ(4 * p - 8, jacobian_vect[0][20 * 10 + p]);
    266     jacobian_vect[0][20 * 10 + p] = 0.0;
    267   }
    268   for (int i = 0; i < jacobian_vect[0].size(); ++i) {
    269     EXPECT_EQ(0.0, jacobian_vect[0][i]);
    270   }
    271 }
    272 
    273 // Takes 3 parameter blocks:
    274 //     parameters[0] (x) is size 1.
    275 //     parameters[1] (y) is size 2.
    276 //     parameters[2] (z) is size 3.
    277 // Emits 7 residuals:
    278 //     A: x[0] (= sum_x)
    279 //     B: y[0] + 2.0 * y[1] (= sum_y)
    280 //     C: z[0] + 3.0 * z[1] + 6.0 * z[2] (= sum_z)
    281 //     D: sum_x * sum_y
    282 //     E: sum_y * sum_z
    283 //     F: sum_x * sum_z
    284 //     G: sum_x * sum_y * sum_z
    285 class MyThreeParameterCostFunctor {
    286  public:
    287   template <typename T>
    288   bool operator()(T const* const* parameters, T* residuals) const {
    289     const T* x = parameters[0];
    290     const T* y = parameters[1];
    291     const T* z = parameters[2];
    292 
    293     T sum_x = x[0];
    294     T sum_y = y[0] + 2.0 * y[1];
    295     T sum_z = z[0] + 3.0 * z[1] + 6.0 * z[2];
    296 
    297     residuals[0] = sum_x;
    298     residuals[1] = sum_y;
    299     residuals[2] = sum_z;
    300     residuals[3] = sum_x * sum_y;
    301     residuals[4] = sum_y * sum_z;
    302     residuals[5] = sum_x * sum_z;
    303     residuals[6] = sum_x * sum_y * sum_z;
    304     return true;
    305   }
    306 };
    307 
    308 class ThreeParameterCostFunctorTest : public ::testing::Test {
    309  protected:
    310   virtual void SetUp() {
    311     // Prepare the parameters.
    312     x_.resize(1);
    313     x_[0] = 0.0;
    314 
    315     y_.resize(2);
    316     y_[0] = 1.0;
    317     y_[1] = 3.0;
    318 
    319     z_.resize(3);
    320     z_[0] = 2.0;
    321     z_[1] = 4.0;
    322     z_[2] = 6.0;
    323 
    324     parameter_blocks_.resize(3);
    325     parameter_blocks_[0] = &x_[0];
    326     parameter_blocks_[1] = &y_[0];
    327     parameter_blocks_[2] = &z_[0];
    328 
    329     // Prepare the cost function.
    330     typedef DynamicAutoDiffCostFunction<MyThreeParameterCostFunctor, 3>
    331       DynamicMyThreeParameterCostFunction;
    332     DynamicMyThreeParameterCostFunction * cost_function =
    333       new DynamicMyThreeParameterCostFunction(
    334         new MyThreeParameterCostFunctor());
    335     cost_function->AddParameterBlock(1);
    336     cost_function->AddParameterBlock(2);
    337     cost_function->AddParameterBlock(3);
    338     cost_function->SetNumResiduals(7);
    339 
    340     cost_function_.reset(cost_function);
    341 
    342     // Setup jacobian data.
    343     jacobian_vect_.resize(3);
    344     jacobian_vect_[0].resize(7 * x_.size(), -100000);
    345     jacobian_vect_[1].resize(7 * y_.size(), -100000);
    346     jacobian_vect_[2].resize(7 * z_.size(), -100000);
    347 
    348     // Prepare the expected residuals.
    349     const double sum_x = x_[0];
    350     const double sum_y = y_[0] + 2.0 * y_[1];
    351     const double sum_z = z_[0] + 3.0 * z_[1] + 6.0 * z_[2];
    352 
    353     expected_residuals_.resize(7);
    354     expected_residuals_[0] = sum_x;
    355     expected_residuals_[1] = sum_y;
    356     expected_residuals_[2] = sum_z;
    357     expected_residuals_[3] = sum_x * sum_y;
    358     expected_residuals_[4] = sum_y * sum_z;
    359     expected_residuals_[5] = sum_x * sum_z;
    360     expected_residuals_[6] = sum_x * sum_y * sum_z;
    361 
    362     // Prepare the expected jacobian entries.
    363     expected_jacobian_x_.resize(7);
    364     expected_jacobian_x_[0] = 1.0;
    365     expected_jacobian_x_[1] = 0.0;
    366     expected_jacobian_x_[2] = 0.0;
    367     expected_jacobian_x_[3] = sum_y;
    368     expected_jacobian_x_[4] = 0.0;
    369     expected_jacobian_x_[5] = sum_z;
    370     expected_jacobian_x_[6] = sum_y * sum_z;
    371 
    372     expected_jacobian_y_.resize(14);
    373     expected_jacobian_y_[0] = 0.0;
    374     expected_jacobian_y_[1] = 0.0;
    375     expected_jacobian_y_[2] = 1.0;
    376     expected_jacobian_y_[3] = 2.0;
    377     expected_jacobian_y_[4] = 0.0;
    378     expected_jacobian_y_[5] = 0.0;
    379     expected_jacobian_y_[6] = sum_x;
    380     expected_jacobian_y_[7] = 2.0 * sum_x;
    381     expected_jacobian_y_[8] = sum_z;
    382     expected_jacobian_y_[9] = 2.0 * sum_z;
    383     expected_jacobian_y_[10] = 0.0;
    384     expected_jacobian_y_[11] = 0.0;
    385     expected_jacobian_y_[12] = sum_x * sum_z;
    386     expected_jacobian_y_[13] = 2.0 * sum_x * sum_z;
    387 
    388     expected_jacobian_z_.resize(21);
    389     expected_jacobian_z_[0] = 0.0;
    390     expected_jacobian_z_[1] = 0.0;
    391     expected_jacobian_z_[2] = 0.0;
    392     expected_jacobian_z_[3] = 0.0;
    393     expected_jacobian_z_[4] = 0.0;
    394     expected_jacobian_z_[5] = 0.0;
    395     expected_jacobian_z_[6] = 1.0;
    396     expected_jacobian_z_[7] = 3.0;
    397     expected_jacobian_z_[8] = 6.0;
    398     expected_jacobian_z_[9] = 0.0;
    399     expected_jacobian_z_[10] = 0.0;
    400     expected_jacobian_z_[11] = 0.0;
    401     expected_jacobian_z_[12] = sum_y;
    402     expected_jacobian_z_[13] = 3.0 * sum_y;
    403     expected_jacobian_z_[14] = 6.0 * sum_y;
    404     expected_jacobian_z_[15] = sum_x;
    405     expected_jacobian_z_[16] = 3.0 * sum_x;
    406     expected_jacobian_z_[17] = 6.0 * sum_x;
    407     expected_jacobian_z_[18] = sum_x * sum_y;
    408     expected_jacobian_z_[19] = 3.0 * sum_x * sum_y;
    409     expected_jacobian_z_[20] = 6.0 * sum_x * sum_y;
    410   }
    411 
    412  protected:
    413   vector<double> x_;
    414   vector<double> y_;
    415   vector<double> z_;
    416 
    417   vector<double*> parameter_blocks_;
    418 
    419   scoped_ptr<CostFunction> cost_function_;
    420 
    421   vector<vector<double> > jacobian_vect_;
    422 
    423   vector<double> expected_residuals_;
    424 
    425   vector<double> expected_jacobian_x_;
    426   vector<double> expected_jacobian_y_;
    427   vector<double> expected_jacobian_z_;
    428 };
    429 
    430 TEST_F(ThreeParameterCostFunctorTest, TestThreeParameterResiduals) {
    431   vector<double> residuals(7, -100000);
    432   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    433                                        residuals.data(),
    434                                        NULL));
    435   for (int i = 0; i < 7; ++i) {
    436     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    437   }
    438 }
    439 
    440 TEST_F(ThreeParameterCostFunctorTest, TestThreeParameterJacobian) {
    441   vector<double> residuals(7, -100000);
    442 
    443   vector<double*> jacobian;
    444   jacobian.push_back(jacobian_vect_[0].data());
    445   jacobian.push_back(jacobian_vect_[1].data());
    446   jacobian.push_back(jacobian_vect_[2].data());
    447 
    448   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    449                                        residuals.data(),
    450                                        jacobian.data()));
    451 
    452   for (int i = 0; i < 7; ++i) {
    453     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    454   }
    455 
    456   for (int i = 0; i < 7; ++i) {
    457     EXPECT_EQ(expected_jacobian_x_[i], jacobian[0][i]);
    458   }
    459 
    460   for (int i = 0; i < 14; ++i) {
    461     EXPECT_EQ(expected_jacobian_y_[i], jacobian[1][i]);
    462   }
    463 
    464   for (int i = 0; i < 21; ++i) {
    465     EXPECT_EQ(expected_jacobian_z_[i], jacobian[2][i]);
    466   }
    467 }
    468 
    469 TEST_F(ThreeParameterCostFunctorTest,
    470        ThreeParameterJacobianWithFirstAndLastParameterBlockConstant) {
    471   vector<double> residuals(7, -100000);
    472 
    473   vector<double*> jacobian;
    474   jacobian.push_back(NULL);
    475   jacobian.push_back(jacobian_vect_[1].data());
    476   jacobian.push_back(NULL);
    477 
    478   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    479                                        residuals.data(),
    480                                        jacobian.data()));
    481 
    482   for (int i = 0; i < 7; ++i) {
    483     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    484   }
    485 
    486   for (int i = 0; i < 14; ++i) {
    487     EXPECT_EQ(expected_jacobian_y_[i], jacobian[1][i]);
    488   }
    489 }
    490 
    491 TEST_F(ThreeParameterCostFunctorTest,
    492        ThreeParameterJacobianWithSecondParameterBlockConstant) {
    493   vector<double> residuals(7, -100000);
    494 
    495   vector<double*> jacobian;
    496   jacobian.push_back(jacobian_vect_[0].data());
    497   jacobian.push_back(NULL);
    498   jacobian.push_back(jacobian_vect_[2].data());
    499 
    500   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    501                                        residuals.data(),
    502                                        jacobian.data()));
    503 
    504   for (int i = 0; i < 7; ++i) {
    505     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    506   }
    507 
    508   for (int i = 0; i < 7; ++i) {
    509     EXPECT_EQ(expected_jacobian_x_[i], jacobian[0][i]);
    510   }
    511 
    512   for (int i = 0; i < 21; ++i) {
    513     EXPECT_EQ(expected_jacobian_z_[i], jacobian[2][i]);
    514   }
    515 }
    516 
    517 // Takes 6 parameter blocks all of size 1:
    518 //     x0, y0, y1, z0, z1, z2
    519 // Same 7 residuals as MyThreeParameterCostFunctor.
    520 // Naming convention for tests is (V)ariable and (C)onstant.
    521 class MySixParameterCostFunctor {
    522  public:
    523   template <typename T>
    524   bool operator()(T const* const* parameters, T* residuals) const {
    525     const T* x0 = parameters[0];
    526     const T* y0 = parameters[1];
    527     const T* y1 = parameters[2];
    528     const T* z0 = parameters[3];
    529     const T* z1 = parameters[4];
    530     const T* z2 = parameters[5];
    531 
    532     T sum_x = x0[0];
    533     T sum_y = y0[0] + 2.0 * y1[0];
    534     T sum_z = z0[0] + 3.0 * z1[0] + 6.0 * z2[0];
    535 
    536     residuals[0] = sum_x;
    537     residuals[1] = sum_y;
    538     residuals[2] = sum_z;
    539     residuals[3] = sum_x * sum_y;
    540     residuals[4] = sum_y * sum_z;
    541     residuals[5] = sum_x * sum_z;
    542     residuals[6] = sum_x * sum_y * sum_z;
    543     return true;
    544   }
    545 };
    546 
    547 class SixParameterCostFunctorTest : public ::testing::Test {
    548  protected:
    549   virtual void SetUp() {
    550     // Prepare the parameters.
    551     x0_ = 0.0;
    552     y0_ = 1.0;
    553     y1_ = 3.0;
    554     z0_ = 2.0;
    555     z1_ = 4.0;
    556     z2_ = 6.0;
    557 
    558     parameter_blocks_.resize(6);
    559     parameter_blocks_[0] = &x0_;
    560     parameter_blocks_[1] = &y0_;
    561     parameter_blocks_[2] = &y1_;
    562     parameter_blocks_[3] = &z0_;
    563     parameter_blocks_[4] = &z1_;
    564     parameter_blocks_[5] = &z2_;
    565 
    566     // Prepare the cost function.
    567     typedef DynamicAutoDiffCostFunction<MySixParameterCostFunctor, 3>
    568       DynamicMySixParameterCostFunction;
    569     DynamicMySixParameterCostFunction * cost_function =
    570       new DynamicMySixParameterCostFunction(
    571         new MySixParameterCostFunctor());
    572     for (int i = 0; i < 6; ++i) {
    573       cost_function->AddParameterBlock(1);
    574     }
    575     cost_function->SetNumResiduals(7);
    576 
    577     cost_function_.reset(cost_function);
    578 
    579     // Setup jacobian data.
    580     jacobian_vect_.resize(6);
    581     for (int i = 0; i < 6; ++i) {
    582       jacobian_vect_[i].resize(7, -100000);
    583     }
    584 
    585     // Prepare the expected residuals.
    586     const double sum_x = x0_;
    587     const double sum_y = y0_ + 2.0 * y1_;
    588     const double sum_z = z0_ + 3.0 * z1_ + 6.0 * z2_;
    589 
    590     expected_residuals_.resize(7);
    591     expected_residuals_[0] = sum_x;
    592     expected_residuals_[1] = sum_y;
    593     expected_residuals_[2] = sum_z;
    594     expected_residuals_[3] = sum_x * sum_y;
    595     expected_residuals_[4] = sum_y * sum_z;
    596     expected_residuals_[5] = sum_x * sum_z;
    597     expected_residuals_[6] = sum_x * sum_y * sum_z;
    598 
    599     // Prepare the expected jacobian entries.
    600     expected_jacobians_.resize(6);
    601     expected_jacobians_[0].resize(7);
    602     expected_jacobians_[0][0] = 1.0;
    603     expected_jacobians_[0][1] = 0.0;
    604     expected_jacobians_[0][2] = 0.0;
    605     expected_jacobians_[0][3] = sum_y;
    606     expected_jacobians_[0][4] = 0.0;
    607     expected_jacobians_[0][5] = sum_z;
    608     expected_jacobians_[0][6] = sum_y * sum_z;
    609 
    610     expected_jacobians_[1].resize(7);
    611     expected_jacobians_[1][0] = 0.0;
    612     expected_jacobians_[1][1] = 1.0;
    613     expected_jacobians_[1][2] = 0.0;
    614     expected_jacobians_[1][3] = sum_x;
    615     expected_jacobians_[1][4] = sum_z;
    616     expected_jacobians_[1][5] = 0.0;
    617     expected_jacobians_[1][6] = sum_x * sum_z;
    618 
    619     expected_jacobians_[2].resize(7);
    620     expected_jacobians_[2][0] = 0.0;
    621     expected_jacobians_[2][1] = 2.0;
    622     expected_jacobians_[2][2] = 0.0;
    623     expected_jacobians_[2][3] = 2.0 * sum_x;
    624     expected_jacobians_[2][4] = 2.0 * sum_z;
    625     expected_jacobians_[2][5] = 0.0;
    626     expected_jacobians_[2][6] = 2.0 * sum_x * sum_z;
    627 
    628     expected_jacobians_[3].resize(7);
    629     expected_jacobians_[3][0] = 0.0;
    630     expected_jacobians_[3][1] = 0.0;
    631     expected_jacobians_[3][2] = 1.0;
    632     expected_jacobians_[3][3] = 0.0;
    633     expected_jacobians_[3][4] = sum_y;
    634     expected_jacobians_[3][5] = sum_x;
    635     expected_jacobians_[3][6] = sum_x * sum_y;
    636 
    637     expected_jacobians_[4].resize(7);
    638     expected_jacobians_[4][0] = 0.0;
    639     expected_jacobians_[4][1] = 0.0;
    640     expected_jacobians_[4][2] = 3.0;
    641     expected_jacobians_[4][3] = 0.0;
    642     expected_jacobians_[4][4] = 3.0 * sum_y;
    643     expected_jacobians_[4][5] = 3.0 * sum_x;
    644     expected_jacobians_[4][6] = 3.0 * sum_x * sum_y;
    645 
    646     expected_jacobians_[5].resize(7);
    647     expected_jacobians_[5][0] = 0.0;
    648     expected_jacobians_[5][1] = 0.0;
    649     expected_jacobians_[5][2] = 6.0;
    650     expected_jacobians_[5][3] = 0.0;
    651     expected_jacobians_[5][4] = 6.0 * sum_y;
    652     expected_jacobians_[5][5] = 6.0 * sum_x;
    653     expected_jacobians_[5][6] = 6.0 * sum_x * sum_y;
    654   }
    655 
    656  protected:
    657   double x0_;
    658   double y0_;
    659   double y1_;
    660   double z0_;
    661   double z1_;
    662   double z2_;
    663 
    664   vector<double*> parameter_blocks_;
    665 
    666   scoped_ptr<CostFunction> cost_function_;
    667 
    668   vector<vector<double> > jacobian_vect_;
    669 
    670   vector<double> expected_residuals_;
    671   vector<vector<double> > expected_jacobians_;
    672 };
    673 
    674 TEST_F(SixParameterCostFunctorTest, TestSixParameterResiduals) {
    675   vector<double> residuals(7, -100000);
    676   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    677                                        residuals.data(),
    678                                        NULL));
    679   for (int i = 0; i < 7; ++i) {
    680     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    681   }
    682 }
    683 
    684 TEST_F(SixParameterCostFunctorTest, TestSixParameterJacobian) {
    685   vector<double> residuals(7, -100000);
    686 
    687   vector<double*> jacobian;
    688   jacobian.push_back(jacobian_vect_[0].data());
    689   jacobian.push_back(jacobian_vect_[1].data());
    690   jacobian.push_back(jacobian_vect_[2].data());
    691   jacobian.push_back(jacobian_vect_[3].data());
    692   jacobian.push_back(jacobian_vect_[4].data());
    693   jacobian.push_back(jacobian_vect_[5].data());
    694 
    695   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    696                                        residuals.data(),
    697                                        jacobian.data()));
    698 
    699   for (int i = 0; i < 7; ++i) {
    700     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    701   }
    702 
    703   for (int i = 0; i < 6; ++i) {
    704     for (int j = 0; j < 7; ++j) {
    705       EXPECT_EQ(expected_jacobians_[i][j], jacobian[i][j]);
    706     }
    707   }
    708 }
    709 
    710 TEST_F(SixParameterCostFunctorTest, TestSixParameterJacobianVVCVVC) {
    711   vector<double> residuals(7, -100000);
    712 
    713   vector<double*> jacobian;
    714   jacobian.push_back(jacobian_vect_[0].data());
    715   jacobian.push_back(jacobian_vect_[1].data());
    716   jacobian.push_back(NULL);
    717   jacobian.push_back(jacobian_vect_[3].data());
    718   jacobian.push_back(jacobian_vect_[4].data());
    719   jacobian.push_back(NULL);
    720 
    721   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    722                                        residuals.data(),
    723                                        jacobian.data()));
    724 
    725   for (int i = 0; i < 7; ++i) {
    726     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    727   }
    728 
    729   for (int i = 0; i < 6; ++i) {
    730     // Skip the constant variables.
    731     if (i == 2 || i == 5) {
    732       continue;
    733     }
    734 
    735     for (int j = 0; j < 7; ++j) {
    736       EXPECT_EQ(expected_jacobians_[i][j], jacobian[i][j]);
    737     }
    738   }
    739 }
    740 
    741 TEST_F(SixParameterCostFunctorTest, TestSixParameterJacobianVCCVCV) {
    742   vector<double> residuals(7, -100000);
    743 
    744   vector<double*> jacobian;
    745   jacobian.push_back(jacobian_vect_[0].data());
    746   jacobian.push_back(NULL);
    747   jacobian.push_back(NULL);
    748   jacobian.push_back(jacobian_vect_[3].data());
    749   jacobian.push_back(NULL);
    750   jacobian.push_back(jacobian_vect_[5].data());
    751 
    752   EXPECT_TRUE(cost_function_->Evaluate(parameter_blocks_.data(),
    753                                        residuals.data(),
    754                                        jacobian.data()));
    755 
    756   for (int i = 0; i < 7; ++i) {
    757     EXPECT_EQ(expected_residuals_[i], residuals[i]);
    758   }
    759 
    760   for (int i = 0; i < 6; ++i) {
    761     // Skip the constant variables.
    762     if (i == 1 || i == 2 || i == 4) {
    763       continue;
    764     }
    765 
    766     for (int j = 0; j < 7; ++j) {
    767       EXPECT_EQ(expected_jacobians_[i][j], jacobian[i][j]);
    768     }
    769   }
    770 }
    771 
    772 }  // namespace internal
    773 }  // namespace ceres
    774