Home | History | Annotate | Download | only in ceres
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 2013 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: sameeragarwal (at) google.com (Sameer Agarwal)
     30 //
     31 // CostFunctionToFunctor is an adapter class that allows users to use
     32 // CostFunction objects in templated functors which are to be used for
     33 // automatic differentiation.  This allows the user to seamlessly mix
     34 // analytic, numeric and automatic differentiation.
     35 //
     36 // For example, let us assume that
     37 //
     38 //  class IntrinsicProjection : public SizedCostFunction<2, 5, 3> {
     39 //    public:
     40 //      IntrinsicProjection(const double* observations);
     41 //      virtual bool Evaluate(double const* const* parameters,
     42 //                            double* residuals,
     43 //                            double** jacobians) const;
     44 //  };
     45 //
     46 // is a cost function that implements the projection of a point in its
     47 // local coordinate system onto its image plane and subtracts it from
     48 // the observed point projection. It can compute its residual and
     49 // either via analytic or numerical differentiation can compute its
     50 // jacobians.
     51 //
     52 // Now we would like to compose the action of this CostFunction with
     53 // the action of camera extrinsics, i.e., rotation and
     54 // translation. Say we have a templated function
     55 //
     56 //   template<typename T>
     57 //   void RotateAndTranslatePoint(const T* rotation,
     58 //                                const T* translation,
     59 //                                const T* point,
     60 //                                T* result);
     61 //
     62 // Then we can now do the following,
     63 //
     64 // struct CameraProjection {
     65 //   CameraProjection(double* observation) {
     66 //     intrinsic_projection_.reset(
     67 //         new CostFunctionToFunctor<2, 5, 3>(
     68 //             new IntrinsicProjection(observation_)));
     69 //   }
     70 //   template <typename T>
     71 //   bool operator()(const T* rotation,
     72 //                   const T* translation,
     73 //                   const T* intrinsics,
     74 //                   const T* point,
     75 //                   T* residual) const {
     76 //     T transformed_point[3];
     77 //     RotateAndTranslatePoint(rotation, translation, point, transformed_point);
     78 //
     79 //     // Note that we call intrinsic_projection_, just like it was
     80 //     // any other templated functor.
     81 //
     82 //     return (*intrinsic_projection_)(intrinsics, transformed_point, residual);
     83 //   }
     84 //
     85 //  private:
     86 //   scoped_ptr<CostFunctionToFunctor<2,5,3> > intrinsic_projection_;
     87 // };
     88 
     89 #ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
     90 #define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
     91 
     92 #include <numeric>
     93 #include <vector>
     94 
     95 #include "ceres/cost_function.h"
     96 #include "ceres/internal/fixed_array.h"
     97 #include "ceres/internal/port.h"
     98 #include "ceres/internal/scoped_ptr.h"
     99 
    100 namespace ceres {
    101 
    102 template <int kNumResiduals,
    103           int N0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
    104           int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
    105 class CostFunctionToFunctor {
    106  public:
    107   explicit CostFunctionToFunctor(CostFunction* cost_function)
    108   : cost_function_(cost_function) {
    109     CHECK_NOTNULL(cost_function);
    110 
    111     CHECK_GE(kNumResiduals, 0);
    112     CHECK_EQ(cost_function->num_residuals(), kNumResiduals);
    113 
    114     // This block breaks the 80 column rule to keep it somewhat readable.
    115     CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
    116           ((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
    117           ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
    118           ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
    119           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||
    120           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||
    121           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||
    122           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||
    123           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||
    124           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)))
    125         << "Zero block cannot precede a non-zero block. Block sizes are "
    126         << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
    127         << N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
    128         << N8 << ", " << N9;
    129 
    130     const vector<int32>& parameter_block_sizes =
    131         cost_function->parameter_block_sizes();
    132     const int num_parameter_blocks =
    133         (N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
    134         (N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
    135     CHECK_EQ(parameter_block_sizes.size(), num_parameter_blocks);
    136 
    137     CHECK_EQ(N0, parameter_block_sizes[0]);
    138     if (parameter_block_sizes.size() > 1) CHECK_EQ(N1, parameter_block_sizes[1]);  // NOLINT
    139     if (parameter_block_sizes.size() > 2) CHECK_EQ(N2, parameter_block_sizes[2]);  // NOLINT
    140     if (parameter_block_sizes.size() > 3) CHECK_EQ(N3, parameter_block_sizes[3]);  // NOLINT
    141     if (parameter_block_sizes.size() > 4) CHECK_EQ(N4, parameter_block_sizes[4]);  // NOLINT
    142     if (parameter_block_sizes.size() > 5) CHECK_EQ(N5, parameter_block_sizes[5]);  // NOLINT
    143     if (parameter_block_sizes.size() > 6) CHECK_EQ(N6, parameter_block_sizes[6]);  // NOLINT
    144     if (parameter_block_sizes.size() > 7) CHECK_EQ(N7, parameter_block_sizes[7]);  // NOLINT
    145     if (parameter_block_sizes.size() > 8) CHECK_EQ(N8, parameter_block_sizes[8]);  // NOLINT
    146     if (parameter_block_sizes.size() > 9) CHECK_EQ(N9, parameter_block_sizes[9]);  // NOLINT
    147 
    148     CHECK_EQ(accumulate(parameter_block_sizes.begin(),
    149                         parameter_block_sizes.end(), 0),
    150              N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9);
    151   }
    152 
    153   bool operator()(const double* x0, double* residuals) const {
    154     CHECK_NE(N0, 0);
    155     CHECK_EQ(N1, 0);
    156     CHECK_EQ(N2, 0);
    157     CHECK_EQ(N3, 0);
    158     CHECK_EQ(N4, 0);
    159     CHECK_EQ(N5, 0);
    160     CHECK_EQ(N6, 0);
    161     CHECK_EQ(N7, 0);
    162     CHECK_EQ(N8, 0);
    163     CHECK_EQ(N9, 0);
    164 
    165     return cost_function_->Evaluate(&x0, residuals, NULL);
    166   }
    167 
    168   bool operator()(const double* x0,
    169                   const double* x1,
    170                   double* residuals) const {
    171     CHECK_NE(N0, 0);
    172     CHECK_NE(N1, 0);
    173     CHECK_EQ(N2, 0);
    174     CHECK_EQ(N3, 0);
    175     CHECK_EQ(N4, 0);
    176     CHECK_EQ(N5, 0);
    177     CHECK_EQ(N6, 0);
    178     CHECK_EQ(N7, 0);
    179     CHECK_EQ(N8, 0);
    180     CHECK_EQ(N9, 0);
    181     internal::FixedArray<const double*> parameter_blocks(2);
    182     parameter_blocks[0] = x0;
    183     parameter_blocks[1] = x1;
    184     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    185   }
    186 
    187   bool operator()(const double* x0,
    188                   const double* x1,
    189                   const double* x2,
    190                   double* residuals) const {
    191     CHECK_NE(N0, 0);
    192     CHECK_NE(N1, 0);
    193     CHECK_NE(N2, 0);
    194     CHECK_EQ(N3, 0);
    195     CHECK_EQ(N4, 0);
    196     CHECK_EQ(N5, 0);
    197     CHECK_EQ(N6, 0);
    198     CHECK_EQ(N7, 0);
    199     CHECK_EQ(N8, 0);
    200     CHECK_EQ(N9, 0);
    201     internal::FixedArray<const double*> parameter_blocks(3);
    202     parameter_blocks[0] = x0;
    203     parameter_blocks[1] = x1;
    204     parameter_blocks[2] = x2;
    205     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    206   }
    207 
    208   bool operator()(const double* x0,
    209                   const double* x1,
    210                   const double* x2,
    211                   const double* x3,
    212                   double* residuals) const {
    213     CHECK_NE(N0, 0);
    214     CHECK_NE(N1, 0);
    215     CHECK_NE(N2, 0);
    216     CHECK_NE(N3, 0);
    217     CHECK_EQ(N4, 0);
    218     CHECK_EQ(N5, 0);
    219     CHECK_EQ(N6, 0);
    220     CHECK_EQ(N7, 0);
    221     CHECK_EQ(N8, 0);
    222     CHECK_EQ(N9, 0);
    223     internal::FixedArray<const double*> parameter_blocks(4);
    224     parameter_blocks[0] = x0;
    225     parameter_blocks[1] = x1;
    226     parameter_blocks[2] = x2;
    227     parameter_blocks[3] = x3;
    228     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    229   }
    230 
    231   bool operator()(const double* x0,
    232                   const double* x1,
    233                   const double* x2,
    234                   const double* x3,
    235                   const double* x4,
    236                   double* residuals) const {
    237     CHECK_NE(N0, 0);
    238     CHECK_NE(N1, 0);
    239     CHECK_NE(N2, 0);
    240     CHECK_NE(N3, 0);
    241     CHECK_NE(N4, 0);
    242     CHECK_EQ(N5, 0);
    243     CHECK_EQ(N6, 0);
    244     CHECK_EQ(N7, 0);
    245     CHECK_EQ(N8, 0);
    246     CHECK_EQ(N9, 0);
    247     internal::FixedArray<const double*> parameter_blocks(5);
    248     parameter_blocks[0] = x0;
    249     parameter_blocks[1] = x1;
    250     parameter_blocks[2] = x2;
    251     parameter_blocks[3] = x3;
    252     parameter_blocks[4] = x4;
    253     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    254   }
    255 
    256   bool operator()(const double* x0,
    257                   const double* x1,
    258                   const double* x2,
    259                   const double* x3,
    260                   const double* x4,
    261                   const double* x5,
    262                   double* residuals) const {
    263     CHECK_NE(N0, 0);
    264     CHECK_NE(N1, 0);
    265     CHECK_NE(N2, 0);
    266     CHECK_NE(N3, 0);
    267     CHECK_NE(N4, 0);
    268     CHECK_NE(N5, 0);
    269     CHECK_EQ(N6, 0);
    270     CHECK_EQ(N7, 0);
    271     CHECK_EQ(N8, 0);
    272     CHECK_EQ(N9, 0);
    273     internal::FixedArray<const double*> parameter_blocks(6);
    274     parameter_blocks[0] = x0;
    275     parameter_blocks[1] = x1;
    276     parameter_blocks[2] = x2;
    277     parameter_blocks[3] = x3;
    278     parameter_blocks[4] = x4;
    279     parameter_blocks[5] = x5;
    280     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    281   }
    282 
    283   bool operator()(const double* x0,
    284                   const double* x1,
    285                   const double* x2,
    286                   const double* x3,
    287                   const double* x4,
    288                   const double* x5,
    289                   const double* x6,
    290                   double* residuals) const {
    291     CHECK_NE(N0, 0);
    292     CHECK_NE(N1, 0);
    293     CHECK_NE(N2, 0);
    294     CHECK_NE(N3, 0);
    295     CHECK_NE(N4, 0);
    296     CHECK_NE(N5, 0);
    297     CHECK_NE(N6, 0);
    298     CHECK_EQ(N7, 0);
    299     CHECK_EQ(N8, 0);
    300     CHECK_EQ(N9, 0);
    301     internal::FixedArray<const double*> parameter_blocks(7);
    302     parameter_blocks[0] = x0;
    303     parameter_blocks[1] = x1;
    304     parameter_blocks[2] = x2;
    305     parameter_blocks[3] = x3;
    306     parameter_blocks[4] = x4;
    307     parameter_blocks[5] = x5;
    308     parameter_blocks[6] = x6;
    309     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    310   }
    311 
    312   bool operator()(const double* x0,
    313                   const double* x1,
    314                   const double* x2,
    315                   const double* x3,
    316                   const double* x4,
    317                   const double* x5,
    318                   const double* x6,
    319                   const double* x7,
    320                   double* residuals) const {
    321     CHECK_NE(N0, 0);
    322     CHECK_NE(N1, 0);
    323     CHECK_NE(N2, 0);
    324     CHECK_NE(N3, 0);
    325     CHECK_NE(N4, 0);
    326     CHECK_NE(N5, 0);
    327     CHECK_NE(N6, 0);
    328     CHECK_NE(N7, 0);
    329     CHECK_EQ(N8, 0);
    330     CHECK_EQ(N9, 0);
    331     internal::FixedArray<const double*> parameter_blocks(8);
    332     parameter_blocks[0] = x0;
    333     parameter_blocks[1] = x1;
    334     parameter_blocks[2] = x2;
    335     parameter_blocks[3] = x3;
    336     parameter_blocks[4] = x4;
    337     parameter_blocks[5] = x5;
    338     parameter_blocks[6] = x6;
    339     parameter_blocks[7] = x7;
    340     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    341   }
    342 
    343   bool operator()(const double* x0,
    344                   const double* x1,
    345                   const double* x2,
    346                   const double* x3,
    347                   const double* x4,
    348                   const double* x5,
    349                   const double* x6,
    350                   const double* x7,
    351                   const double* x8,
    352                   double* residuals) const {
    353     CHECK_NE(N0, 0);
    354     CHECK_NE(N1, 0);
    355     CHECK_NE(N2, 0);
    356     CHECK_NE(N3, 0);
    357     CHECK_NE(N4, 0);
    358     CHECK_NE(N5, 0);
    359     CHECK_NE(N6, 0);
    360     CHECK_NE(N7, 0);
    361     CHECK_NE(N8, 0);
    362     CHECK_EQ(N9, 0);
    363     internal::FixedArray<const double*> parameter_blocks(9);
    364     parameter_blocks[0] = x0;
    365     parameter_blocks[1] = x1;
    366     parameter_blocks[2] = x2;
    367     parameter_blocks[3] = x3;
    368     parameter_blocks[4] = x4;
    369     parameter_blocks[5] = x5;
    370     parameter_blocks[6] = x6;
    371     parameter_blocks[7] = x7;
    372     parameter_blocks[8] = x8;
    373     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    374   }
    375 
    376   bool operator()(const double* x0,
    377                   const double* x1,
    378                   const double* x2,
    379                   const double* x3,
    380                   const double* x4,
    381                   const double* x5,
    382                   const double* x6,
    383                   const double* x7,
    384                   const double* x8,
    385                   const double* x9,
    386                   double* residuals) const {
    387     CHECK_NE(N0, 0);
    388     CHECK_NE(N1, 0);
    389     CHECK_NE(N2, 0);
    390     CHECK_NE(N3, 0);
    391     CHECK_NE(N4, 0);
    392     CHECK_NE(N5, 0);
    393     CHECK_NE(N6, 0);
    394     CHECK_NE(N7, 0);
    395     CHECK_NE(N8, 0);
    396     CHECK_NE(N9, 0);
    397     internal::FixedArray<const double*> parameter_blocks(10);
    398     parameter_blocks[0] = x0;
    399     parameter_blocks[1] = x1;
    400     parameter_blocks[2] = x2;
    401     parameter_blocks[3] = x3;
    402     parameter_blocks[4] = x4;
    403     parameter_blocks[5] = x5;
    404     parameter_blocks[6] = x6;
    405     parameter_blocks[7] = x7;
    406     parameter_blocks[8] = x8;
    407     parameter_blocks[9] = x9;
    408     return cost_function_->Evaluate(parameter_blocks.get(), residuals, NULL);
    409   }
    410 
    411   template <typename JetT>
    412   bool operator()(const JetT* x0, JetT* residuals) const {
    413     CHECK_NE(N0, 0);
    414     CHECK_EQ(N1, 0);
    415     CHECK_EQ(N2, 0);
    416     CHECK_EQ(N3, 0);
    417     CHECK_EQ(N4, 0);
    418     CHECK_EQ(N5, 0);
    419     CHECK_EQ(N6, 0);
    420     CHECK_EQ(N7, 0);
    421     CHECK_EQ(N8, 0);
    422     CHECK_EQ(N9, 0);
    423     return EvaluateWithJets(&x0, residuals);
    424   }
    425 
    426   template <typename JetT>
    427   bool operator()(const JetT* x0,
    428                   const JetT* x1,
    429                   JetT* residuals) const {
    430     CHECK_NE(N0, 0);
    431     CHECK_NE(N1, 0);
    432     CHECK_EQ(N2, 0);
    433     CHECK_EQ(N3, 0);
    434     CHECK_EQ(N4, 0);
    435     CHECK_EQ(N5, 0);
    436     CHECK_EQ(N6, 0);
    437     CHECK_EQ(N7, 0);
    438     CHECK_EQ(N8, 0);
    439     CHECK_EQ(N9, 0);
    440     internal::FixedArray<const JetT*> jets(2);
    441     jets[0] = x0;
    442     jets[1] = x1;
    443     return EvaluateWithJets(jets.get(), residuals);
    444   }
    445 
    446   template <typename JetT>
    447   bool operator()(const JetT* x0,
    448                   const JetT* x1,
    449                   const JetT* x2,
    450                   JetT* residuals) const {
    451     CHECK_NE(N0, 0);
    452     CHECK_NE(N1, 0);
    453     CHECK_NE(N2, 0);
    454     CHECK_EQ(N3, 0);
    455     CHECK_EQ(N4, 0);
    456     CHECK_EQ(N5, 0);
    457     CHECK_EQ(N6, 0);
    458     CHECK_EQ(N7, 0);
    459     CHECK_EQ(N8, 0);
    460     CHECK_EQ(N9, 0);
    461     internal::FixedArray<const JetT*> jets(3);
    462     jets[0] = x0;
    463     jets[1] = x1;
    464     jets[2] = x2;
    465     return EvaluateWithJets(jets.get(), residuals);
    466   }
    467 
    468   template <typename JetT>
    469   bool operator()(const JetT* x0,
    470                   const JetT* x1,
    471                   const JetT* x2,
    472                   const JetT* x3,
    473                   JetT* residuals) const {
    474     CHECK_NE(N0, 0);
    475     CHECK_NE(N1, 0);
    476     CHECK_NE(N2, 0);
    477     CHECK_NE(N3, 0);
    478     CHECK_EQ(N4, 0);
    479     CHECK_EQ(N5, 0);
    480     CHECK_EQ(N6, 0);
    481     CHECK_EQ(N7, 0);
    482     CHECK_EQ(N8, 0);
    483     CHECK_EQ(N9, 0);
    484     internal::FixedArray<const JetT*> jets(4);
    485     jets[0] = x0;
    486     jets[1] = x1;
    487     jets[2] = x2;
    488     jets[3] = x3;
    489     return EvaluateWithJets(jets.get(), residuals);
    490   }
    491 
    492   template <typename JetT>
    493   bool operator()(const JetT* x0,
    494                   const JetT* x1,
    495                   const JetT* x2,
    496                   const JetT* x3,
    497                   const JetT* x4,
    498                   JetT* residuals) const {
    499     CHECK_NE(N0, 0);
    500     CHECK_NE(N1, 0);
    501     CHECK_NE(N2, 0);
    502     CHECK_NE(N3, 0);
    503     CHECK_NE(N4, 0);
    504     CHECK_EQ(N5, 0);
    505     CHECK_EQ(N6, 0);
    506     CHECK_EQ(N7, 0);
    507     CHECK_EQ(N8, 0);
    508     CHECK_EQ(N9, 0);
    509     internal::FixedArray<const JetT*> jets(5);
    510     jets[0] = x0;
    511     jets[1] = x1;
    512     jets[2] = x2;
    513     jets[3] = x3;
    514     jets[4] = x4;
    515     return EvaluateWithJets(jets.get(), residuals);
    516   }
    517 
    518   template <typename JetT>
    519   bool operator()(const JetT* x0,
    520                   const JetT* x1,
    521                   const JetT* x2,
    522                   const JetT* x3,
    523                   const JetT* x4,
    524                   const JetT* x5,
    525                   JetT* residuals) const {
    526     CHECK_NE(N0, 0);
    527     CHECK_NE(N1, 0);
    528     CHECK_NE(N2, 0);
    529     CHECK_NE(N3, 0);
    530     CHECK_NE(N4, 0);
    531     CHECK_NE(N5, 0);
    532     CHECK_EQ(N6, 0);
    533     CHECK_EQ(N7, 0);
    534     CHECK_EQ(N8, 0);
    535     CHECK_EQ(N9, 0);
    536     internal::FixedArray<const JetT*> jets(6);
    537     jets[0] = x0;
    538     jets[1] = x1;
    539     jets[2] = x2;
    540     jets[3] = x3;
    541     jets[4] = x4;
    542     jets[5] = x5;
    543     return EvaluateWithJets(jets.get(), residuals);
    544   }
    545 
    546   template <typename JetT>
    547   bool operator()(const JetT* x0,
    548                   const JetT* x1,
    549                   const JetT* x2,
    550                   const JetT* x3,
    551                   const JetT* x4,
    552                   const JetT* x5,
    553                   const JetT* x6,
    554                   JetT* residuals) const {
    555     CHECK_NE(N0, 0);
    556     CHECK_NE(N1, 0);
    557     CHECK_NE(N2, 0);
    558     CHECK_NE(N3, 0);
    559     CHECK_NE(N4, 0);
    560     CHECK_NE(N5, 0);
    561     CHECK_NE(N6, 0);
    562     CHECK_EQ(N7, 0);
    563     CHECK_EQ(N8, 0);
    564     CHECK_EQ(N9, 0);
    565     internal::FixedArray<const JetT*> jets(7);
    566     jets[0] = x0;
    567     jets[1] = x1;
    568     jets[2] = x2;
    569     jets[3] = x3;
    570     jets[4] = x4;
    571     jets[5] = x5;
    572     jets[6] = x6;
    573     return EvaluateWithJets(jets.get(), residuals);
    574   }
    575 
    576   template <typename JetT>
    577   bool operator()(const JetT* x0,
    578                   const JetT* x1,
    579                   const JetT* x2,
    580                   const JetT* x3,
    581                   const JetT* x4,
    582                   const JetT* x5,
    583                   const JetT* x6,
    584                   const JetT* x7,
    585                   JetT* residuals) const {
    586     CHECK_NE(N0, 0);
    587     CHECK_NE(N1, 0);
    588     CHECK_NE(N2, 0);
    589     CHECK_NE(N3, 0);
    590     CHECK_NE(N4, 0);
    591     CHECK_NE(N5, 0);
    592     CHECK_NE(N6, 0);
    593     CHECK_NE(N7, 0);
    594     CHECK_EQ(N8, 0);
    595     CHECK_EQ(N9, 0);
    596     internal::FixedArray<const JetT*> jets(8);
    597     jets[0] = x0;
    598     jets[1] = x1;
    599     jets[2] = x2;
    600     jets[3] = x3;
    601     jets[4] = x4;
    602     jets[5] = x5;
    603     jets[6] = x6;
    604     jets[7] = x7;
    605     return EvaluateWithJets(jets.get(), residuals);
    606   }
    607 
    608   template <typename JetT>
    609   bool operator()(const JetT* x0,
    610                   const JetT* x1,
    611                   const JetT* x2,
    612                   const JetT* x3,
    613                   const JetT* x4,
    614                   const JetT* x5,
    615                   const JetT* x6,
    616                   const JetT* x7,
    617                   const JetT* x8,
    618                   JetT* residuals) const {
    619     CHECK_NE(N0, 0);
    620     CHECK_NE(N1, 0);
    621     CHECK_NE(N2, 0);
    622     CHECK_NE(N3, 0);
    623     CHECK_NE(N4, 0);
    624     CHECK_NE(N5, 0);
    625     CHECK_NE(N6, 0);
    626     CHECK_NE(N7, 0);
    627     CHECK_NE(N8, 0);
    628     CHECK_EQ(N9, 0);
    629     internal::FixedArray<const JetT*> jets(9);
    630     jets[0] = x0;
    631     jets[1] = x1;
    632     jets[2] = x2;
    633     jets[3] = x3;
    634     jets[4] = x4;
    635     jets[5] = x5;
    636     jets[6] = x6;
    637     jets[7] = x7;
    638     jets[8] = x8;
    639     return EvaluateWithJets(jets.get(), residuals);
    640   }
    641 
    642   template <typename JetT>
    643   bool operator()(const JetT* x0,
    644                   const JetT* x1,
    645                   const JetT* x2,
    646                   const JetT* x3,
    647                   const JetT* x4,
    648                   const JetT* x5,
    649                   const JetT* x6,
    650                   const JetT* x7,
    651                   const JetT* x8,
    652                   const JetT* x9,
    653                   JetT* residuals) const {
    654     CHECK_NE(N0, 0);
    655     CHECK_NE(N1, 0);
    656     CHECK_NE(N2, 0);
    657     CHECK_NE(N3, 0);
    658     CHECK_NE(N4, 0);
    659     CHECK_NE(N5, 0);
    660     CHECK_NE(N6, 0);
    661     CHECK_NE(N7, 0);
    662     CHECK_NE(N8, 0);
    663     CHECK_NE(N9, 0);
    664     internal::FixedArray<const JetT*> jets(10);
    665     jets[0] = x0;
    666     jets[1] = x1;
    667     jets[2] = x2;
    668     jets[3] = x3;
    669     jets[4] = x4;
    670     jets[5] = x5;
    671     jets[6] = x6;
    672     jets[7] = x7;
    673     jets[8] = x8;
    674     jets[9] = x9;
    675     return EvaluateWithJets(jets.get(), residuals);
    676   }
    677 
    678  private:
    679   template <typename JetT>
    680   bool EvaluateWithJets(const JetT** inputs, JetT* output) const {
    681     const int kNumParameters =  N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9;
    682     const vector<int32>& parameter_block_sizes =
    683         cost_function_->parameter_block_sizes();
    684     const int num_parameter_blocks = parameter_block_sizes.size();
    685     const int num_residuals = cost_function_->num_residuals();
    686 
    687     internal::FixedArray<double> parameters(kNumParameters);
    688     internal::FixedArray<double*> parameter_blocks(num_parameter_blocks);
    689     internal::FixedArray<double> jacobians(num_residuals * kNumParameters);
    690     internal::FixedArray<double*> jacobian_blocks(num_parameter_blocks);
    691     internal::FixedArray<double> residuals(num_residuals);
    692 
    693     // Build a set of arrays to get the residuals and jacobians from
    694     // the CostFunction wrapped by this functor.
    695     double* parameter_ptr = parameters.get();
    696     double* jacobian_ptr = jacobians.get();
    697     for (int i = 0; i < num_parameter_blocks; ++i) {
    698       parameter_blocks[i] = parameter_ptr;
    699       jacobian_blocks[i] = jacobian_ptr;
    700       for (int j = 0; j < parameter_block_sizes[i]; ++j) {
    701         *parameter_ptr++ = inputs[i][j].a;
    702       }
    703       jacobian_ptr += num_residuals * parameter_block_sizes[i];
    704     }
    705 
    706     if (!cost_function_->Evaluate(parameter_blocks.get(),
    707                                   residuals.get(),
    708                                   jacobian_blocks.get())) {
    709       return false;
    710     }
    711 
    712     // Now that we have the incoming Jets, which are carrying the
    713     // partial derivatives of each of the inputs w.r.t to some other
    714     // underlying parameters. The derivative of the outputs of the
    715     // cost function w.r.t to the same underlying parameters can now
    716     // be computed by applying the chain rule.
    717     //
    718     //  d output[i]               d output[i]   d input[j]
    719     //  --------------  = sum_j   ----------- * ------------
    720     //  d parameter[k]            d input[j]    d parameter[k]
    721     //
    722     // d input[j]
    723     // --------------  = inputs[j], so
    724     // d parameter[k]
    725     //
    726     //  outputJet[i]  = sum_k jacobian[i][k] * inputJet[k]
    727     //
    728     // The following loop, iterates over the residuals, computing one
    729     // output jet at a time.
    730     for (int i = 0; i < num_residuals; ++i) {
    731       output[i].a = residuals[i];
    732       output[i].v.setZero();
    733 
    734       for (int j = 0; j < num_parameter_blocks; ++j) {
    735         const int32 block_size = parameter_block_sizes[j];
    736         for (int k = 0; k < parameter_block_sizes[j]; ++k) {
    737           output[i].v +=
    738               jacobian_blocks[j][i * block_size + k] * inputs[j][k].v;
    739         }
    740       }
    741     }
    742 
    743     return true;
    744   }
    745 
    746  private:
    747   internal::scoped_ptr<CostFunction> cost_function_;
    748 };
    749 
    750 }  // namespace ceres
    751 
    752 #endif  // CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
    753