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@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:
CostFunctionToFunctor(CostFunction * cost_function)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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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 
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
operator()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>
EvaluateWithJets(const JetT ** inputs,JetT * output)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