6c67ac0f9376e7530c218fb0469032403612132d
[blender.git] / extern / ceres / include / ceres / cost_function_to_functor.h
1 // Ceres Solver - A fast non-linear least squares minimizer
2 // Copyright 2015 Google Inc. All rights reserved.
3 // http://ceres-solver.org/
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 // SizedCostFunction 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* observation);
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(const double* observation)
66 //       : intrinsic_projection_(new IntrinsicProjection(observation)) {
67 //   }
68 //   template <typename T>
69 //   bool operator()(const T* rotation,
70 //                   const T* translation,
71 //                   const T* intrinsics,
72 //                   const T* point,
73 //                   T* residual) const {
74 //     T transformed_point[3];
75 //     RotateAndTranslatePoint(rotation, translation, point, transformed_point);
76 //
77 //     // Note that we call intrinsic_projection_, just like it was
78 //     // any other templated functor.
79 //
80 //     return intrinsic_projection_(intrinsics, transformed_point, residual);
81 //   }
82 //
83 //  private:
84 //   CostFunctionToFunctor<2,5,3> intrinsic_projection_;
85 // };
86
87 #ifndef CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
88 #define CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_
89
90 #include <numeric>
91 #include <vector>
92
93 #include "ceres/cost_function.h"
94 #include "ceres/dynamic_cost_function_to_functor.h"
95 #include "ceres/internal/fixed_array.h"
96 #include "ceres/internal/port.h"
97 #include "ceres/internal/scoped_ptr.h"
98
99 namespace ceres {
100
101 template <int kNumResiduals,
102           int N0, int N1 = 0, int N2 = 0, int N3 = 0, int N4 = 0,
103           int N5 = 0, int N6 = 0, int N7 = 0, int N8 = 0, int N9 = 0>
104 class CostFunctionToFunctor {
105  public:
106   // Takes ownership of cost_function.
107   explicit CostFunctionToFunctor(CostFunction* cost_function)
108       : cost_functor_(cost_function) {
109     CHECK_NOTNULL(cost_function);
110     CHECK(kNumResiduals > 0 || kNumResiduals == DYNAMIC);
111
112     // This block breaks the 80 column rule to keep it somewhat readable.
113     CHECK((!N1 && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
114           ((N1 > 0) && !N2 && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||
115           ((N1 > 0) && (N2 > 0) && !N3 && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||                                    // NOLINT
116           ((N1 > 0) && (N2 > 0) && (N3 > 0) && !N4 && !N5 && !N6 && !N7 && !N8 && !N9) ||                               // NOLINT
117           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && !N5 && !N6 && !N7 && !N8 && !N9) ||                          // NOLINT
118           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && !N6 && !N7 && !N8 && !N9) ||                     // NOLINT
119           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && !N7 && !N8 && !N9) ||                // NOLINT
120           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && !N8 && !N9) ||           // NOLINT
121           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && !N9) ||      // NOLINT
122           ((N1 > 0) && (N2 > 0) && (N3 > 0) && (N4 > 0) && (N5 > 0) && (N6 > 0) && (N7 > 0) && (N8 > 0) && (N9 > 0)))   // NOLINT
123         << "Zero block cannot precede a non-zero block. Block sizes are "
124         << "(ignore trailing 0s): " << N0 << ", " << N1 << ", " << N2 << ", "
125         << N3 << ", " << N4 << ", " << N5 << ", " << N6 << ", " << N7 << ", "
126         << N8 << ", " << N9;
127
128     const std::vector<int32>& parameter_block_sizes =
129         cost_function->parameter_block_sizes();
130     const int num_parameter_blocks =
131         (N0 > 0) + (N1 > 0) + (N2 > 0) + (N3 > 0) + (N4 > 0) +
132         (N5 > 0) + (N6 > 0) + (N7 > 0) + (N8 > 0) + (N9 > 0);
133     CHECK_EQ(parameter_block_sizes.size(), num_parameter_blocks);
134
135     CHECK_EQ(N0, parameter_block_sizes[0]);
136     if (parameter_block_sizes.size() > 1) CHECK_EQ(N1, parameter_block_sizes[1]);  // NOLINT
137     if (parameter_block_sizes.size() > 2) CHECK_EQ(N2, parameter_block_sizes[2]);  // NOLINT
138     if (parameter_block_sizes.size() > 3) CHECK_EQ(N3, parameter_block_sizes[3]);  // NOLINT
139     if (parameter_block_sizes.size() > 4) CHECK_EQ(N4, parameter_block_sizes[4]);  // NOLINT
140     if (parameter_block_sizes.size() > 5) CHECK_EQ(N5, parameter_block_sizes[5]);  // NOLINT
141     if (parameter_block_sizes.size() > 6) CHECK_EQ(N6, parameter_block_sizes[6]);  // NOLINT
142     if (parameter_block_sizes.size() > 7) CHECK_EQ(N7, parameter_block_sizes[7]);  // NOLINT
143     if (parameter_block_sizes.size() > 8) CHECK_EQ(N8, parameter_block_sizes[8]);  // NOLINT
144     if (parameter_block_sizes.size() > 9) CHECK_EQ(N9, parameter_block_sizes[9]);  // NOLINT
145
146     CHECK_EQ(accumulate(parameter_block_sizes.begin(),
147                         parameter_block_sizes.end(), 0),
148              N0 + N1 + N2 + N3 + N4 + N5 + N6 + N7 + N8 + N9);
149   }
150
151   bool operator()(const double* x0, double* residuals) const {
152     CHECK_NE(N0, 0);
153     CHECK_EQ(N1, 0);
154     CHECK_EQ(N2, 0);
155     CHECK_EQ(N3, 0);
156     CHECK_EQ(N4, 0);
157     CHECK_EQ(N5, 0);
158     CHECK_EQ(N6, 0);
159     CHECK_EQ(N7, 0);
160     CHECK_EQ(N8, 0);
161     CHECK_EQ(N9, 0);
162
163     return cost_functor_(&x0, residuals);
164   }
165
166   bool operator()(const double* x0,
167                   const double* x1,
168                   double* residuals) const {
169     CHECK_NE(N0, 0);
170     CHECK_NE(N1, 0);
171     CHECK_EQ(N2, 0);
172     CHECK_EQ(N3, 0);
173     CHECK_EQ(N4, 0);
174     CHECK_EQ(N5, 0);
175     CHECK_EQ(N6, 0);
176     CHECK_EQ(N7, 0);
177     CHECK_EQ(N8, 0);
178     CHECK_EQ(N9, 0);
179     internal::FixedArray<const double*> parameter_blocks(2);
180     parameter_blocks[0] = x0;
181     parameter_blocks[1] = x1;
182     return cost_functor_(parameter_blocks.get(), residuals);
183   }
184
185   bool operator()(const double* x0,
186                   const double* x1,
187                   const double* x2,
188                   double* residuals) const {
189     CHECK_NE(N0, 0);
190     CHECK_NE(N1, 0);
191     CHECK_NE(N2, 0);
192     CHECK_EQ(N3, 0);
193     CHECK_EQ(N4, 0);
194     CHECK_EQ(N5, 0);
195     CHECK_EQ(N6, 0);
196     CHECK_EQ(N7, 0);
197     CHECK_EQ(N8, 0);
198     CHECK_EQ(N9, 0);
199     internal::FixedArray<const double*> parameter_blocks(3);
200     parameter_blocks[0] = x0;
201     parameter_blocks[1] = x1;
202     parameter_blocks[2] = x2;
203     return cost_functor_(parameter_blocks.get(), residuals);
204   }
205
206   bool operator()(const double* x0,
207                   const double* x1,
208                   const double* x2,
209                   const double* x3,
210                   double* residuals) const {
211     CHECK_NE(N0, 0);
212     CHECK_NE(N1, 0);
213     CHECK_NE(N2, 0);
214     CHECK_NE(N3, 0);
215     CHECK_EQ(N4, 0);
216     CHECK_EQ(N5, 0);
217     CHECK_EQ(N6, 0);
218     CHECK_EQ(N7, 0);
219     CHECK_EQ(N8, 0);
220     CHECK_EQ(N9, 0);
221     internal::FixedArray<const double*> parameter_blocks(4);
222     parameter_blocks[0] = x0;
223     parameter_blocks[1] = x1;
224     parameter_blocks[2] = x2;
225     parameter_blocks[3] = x3;
226     return cost_functor_(parameter_blocks.get(), residuals);
227   }
228
229   bool operator()(const double* x0,
230                   const double* x1,
231                   const double* x2,
232                   const double* x3,
233                   const double* x4,
234                   double* residuals) const {
235     CHECK_NE(N0, 0);
236     CHECK_NE(N1, 0);
237     CHECK_NE(N2, 0);
238     CHECK_NE(N3, 0);
239     CHECK_NE(N4, 0);
240     CHECK_EQ(N5, 0);
241     CHECK_EQ(N6, 0);
242     CHECK_EQ(N7, 0);
243     CHECK_EQ(N8, 0);
244     CHECK_EQ(N9, 0);
245     internal::FixedArray<const double*> parameter_blocks(5);
246     parameter_blocks[0] = x0;
247     parameter_blocks[1] = x1;
248     parameter_blocks[2] = x2;
249     parameter_blocks[3] = x3;
250     parameter_blocks[4] = x4;
251     return cost_functor_(parameter_blocks.get(), residuals);
252   }
253
254   bool operator()(const double* x0,
255                   const double* x1,
256                   const double* x2,
257                   const double* x3,
258                   const double* x4,
259                   const double* x5,
260                   double* residuals) const {
261     CHECK_NE(N0, 0);
262     CHECK_NE(N1, 0);
263     CHECK_NE(N2, 0);
264     CHECK_NE(N3, 0);
265     CHECK_NE(N4, 0);
266     CHECK_NE(N5, 0);
267     CHECK_EQ(N6, 0);
268     CHECK_EQ(N7, 0);
269     CHECK_EQ(N8, 0);
270     CHECK_EQ(N9, 0);
271     internal::FixedArray<const double*> parameter_blocks(6);
272     parameter_blocks[0] = x0;
273     parameter_blocks[1] = x1;
274     parameter_blocks[2] = x2;
275     parameter_blocks[3] = x3;
276     parameter_blocks[4] = x4;
277     parameter_blocks[5] = x5;
278     return cost_functor_(parameter_blocks.get(), residuals);
279   }
280
281   bool operator()(const double* x0,
282                   const double* x1,
283                   const double* x2,
284                   const double* x3,
285                   const double* x4,
286                   const double* x5,
287                   const double* x6,
288                   double* residuals) const {
289     CHECK_NE(N0, 0);
290     CHECK_NE(N1, 0);
291     CHECK_NE(N2, 0);
292     CHECK_NE(N3, 0);
293     CHECK_NE(N4, 0);
294     CHECK_NE(N5, 0);
295     CHECK_NE(N6, 0);
296     CHECK_EQ(N7, 0);
297     CHECK_EQ(N8, 0);
298     CHECK_EQ(N9, 0);
299     internal::FixedArray<const double*> parameter_blocks(7);
300     parameter_blocks[0] = x0;
301     parameter_blocks[1] = x1;
302     parameter_blocks[2] = x2;
303     parameter_blocks[3] = x3;
304     parameter_blocks[4] = x4;
305     parameter_blocks[5] = x5;
306     parameter_blocks[6] = x6;
307     return cost_functor_(parameter_blocks.get(), residuals);
308   }
309
310   bool operator()(const double* x0,
311                   const double* x1,
312                   const double* x2,
313                   const double* x3,
314                   const double* x4,
315                   const double* x5,
316                   const double* x6,
317                   const double* x7,
318                   double* residuals) const {
319     CHECK_NE(N0, 0);
320     CHECK_NE(N1, 0);
321     CHECK_NE(N2, 0);
322     CHECK_NE(N3, 0);
323     CHECK_NE(N4, 0);
324     CHECK_NE(N5, 0);
325     CHECK_NE(N6, 0);
326     CHECK_NE(N7, 0);
327     CHECK_EQ(N8, 0);
328     CHECK_EQ(N9, 0);
329     internal::FixedArray<const double*> parameter_blocks(8);
330     parameter_blocks[0] = x0;
331     parameter_blocks[1] = x1;
332     parameter_blocks[2] = x2;
333     parameter_blocks[3] = x3;
334     parameter_blocks[4] = x4;
335     parameter_blocks[5] = x5;
336     parameter_blocks[6] = x6;
337     parameter_blocks[7] = x7;
338     return cost_functor_(parameter_blocks.get(), residuals);
339   }
340
341   bool operator()(const double* x0,
342                   const double* x1,
343                   const double* x2,
344                   const double* x3,
345                   const double* x4,
346                   const double* x5,
347                   const double* x6,
348                   const double* x7,
349                   const double* x8,
350                   double* residuals) const {
351     CHECK_NE(N0, 0);
352     CHECK_NE(N1, 0);
353     CHECK_NE(N2, 0);
354     CHECK_NE(N3, 0);
355     CHECK_NE(N4, 0);
356     CHECK_NE(N5, 0);
357     CHECK_NE(N6, 0);
358     CHECK_NE(N7, 0);
359     CHECK_NE(N8, 0);
360     CHECK_EQ(N9, 0);
361     internal::FixedArray<const double*> parameter_blocks(9);
362     parameter_blocks[0] = x0;
363     parameter_blocks[1] = x1;
364     parameter_blocks[2] = x2;
365     parameter_blocks[3] = x3;
366     parameter_blocks[4] = x4;
367     parameter_blocks[5] = x5;
368     parameter_blocks[6] = x6;
369     parameter_blocks[7] = x7;
370     parameter_blocks[8] = x8;
371     return cost_functor_(parameter_blocks.get(), residuals);
372   }
373
374   bool operator()(const double* x0,
375                   const double* x1,
376                   const double* x2,
377                   const double* x3,
378                   const double* x4,
379                   const double* x5,
380                   const double* x6,
381                   const double* x7,
382                   const double* x8,
383                   const double* x9,
384                   double* residuals) const {
385     CHECK_NE(N0, 0);
386     CHECK_NE(N1, 0);
387     CHECK_NE(N2, 0);
388     CHECK_NE(N3, 0);
389     CHECK_NE(N4, 0);
390     CHECK_NE(N5, 0);
391     CHECK_NE(N6, 0);
392     CHECK_NE(N7, 0);
393     CHECK_NE(N8, 0);
394     CHECK_NE(N9, 0);
395     internal::FixedArray<const double*> parameter_blocks(10);
396     parameter_blocks[0] = x0;
397     parameter_blocks[1] = x1;
398     parameter_blocks[2] = x2;
399     parameter_blocks[3] = x3;
400     parameter_blocks[4] = x4;
401     parameter_blocks[5] = x5;
402     parameter_blocks[6] = x6;
403     parameter_blocks[7] = x7;
404     parameter_blocks[8] = x8;
405     parameter_blocks[9] = x9;
406     return cost_functor_(parameter_blocks.get(), residuals);
407   }
408
409   template <typename JetT>
410   bool operator()(const JetT* x0, JetT* residuals) const {
411     CHECK_NE(N0, 0);
412     CHECK_EQ(N1, 0);
413     CHECK_EQ(N2, 0);
414     CHECK_EQ(N3, 0);
415     CHECK_EQ(N4, 0);
416     CHECK_EQ(N5, 0);
417     CHECK_EQ(N6, 0);
418     CHECK_EQ(N7, 0);
419     CHECK_EQ(N8, 0);
420     CHECK_EQ(N9, 0);
421     return cost_functor_(&x0, residuals);
422   }
423
424   template <typename JetT>
425   bool operator()(const JetT* x0,
426                   const JetT* x1,
427                   JetT* residuals) const {
428     CHECK_NE(N0, 0);
429     CHECK_NE(N1, 0);
430     CHECK_EQ(N2, 0);
431     CHECK_EQ(N3, 0);
432     CHECK_EQ(N4, 0);
433     CHECK_EQ(N5, 0);
434     CHECK_EQ(N6, 0);
435     CHECK_EQ(N7, 0);
436     CHECK_EQ(N8, 0);
437     CHECK_EQ(N9, 0);
438     internal::FixedArray<const JetT*> jets(2);
439     jets[0] = x0;
440     jets[1] = x1;
441     return cost_functor_(jets.get(), residuals);
442   }
443
444   template <typename JetT>
445   bool operator()(const JetT* x0,
446                   const JetT* x1,
447                   const JetT* x2,
448                   JetT* residuals) const {
449     CHECK_NE(N0, 0);
450     CHECK_NE(N1, 0);
451     CHECK_NE(N2, 0);
452     CHECK_EQ(N3, 0);
453     CHECK_EQ(N4, 0);
454     CHECK_EQ(N5, 0);
455     CHECK_EQ(N6, 0);
456     CHECK_EQ(N7, 0);
457     CHECK_EQ(N8, 0);
458     CHECK_EQ(N9, 0);
459     internal::FixedArray<const JetT*> jets(3);
460     jets[0] = x0;
461     jets[1] = x1;
462     jets[2] = x2;
463     return cost_functor_(jets.get(), residuals);
464   }
465
466   template <typename JetT>
467   bool operator()(const JetT* x0,
468                   const JetT* x1,
469                   const JetT* x2,
470                   const JetT* x3,
471                   JetT* residuals) const {
472     CHECK_NE(N0, 0);
473     CHECK_NE(N1, 0);
474     CHECK_NE(N2, 0);
475     CHECK_NE(N3, 0);
476     CHECK_EQ(N4, 0);
477     CHECK_EQ(N5, 0);
478     CHECK_EQ(N6, 0);
479     CHECK_EQ(N7, 0);
480     CHECK_EQ(N8, 0);
481     CHECK_EQ(N9, 0);
482     internal::FixedArray<const JetT*> jets(4);
483     jets[0] = x0;
484     jets[1] = x1;
485     jets[2] = x2;
486     jets[3] = x3;
487     return cost_functor_(jets.get(), residuals);
488   }
489
490   template <typename JetT>
491   bool operator()(const JetT* x0,
492                   const JetT* x1,
493                   const JetT* x2,
494                   const JetT* x3,
495                   const JetT* x4,
496                   JetT* residuals) const {
497     CHECK_NE(N0, 0);
498     CHECK_NE(N1, 0);
499     CHECK_NE(N2, 0);
500     CHECK_NE(N3, 0);
501     CHECK_NE(N4, 0);
502     CHECK_EQ(N5, 0);
503     CHECK_EQ(N6, 0);
504     CHECK_EQ(N7, 0);
505     CHECK_EQ(N8, 0);
506     CHECK_EQ(N9, 0);
507     internal::FixedArray<const JetT*> jets(5);
508     jets[0] = x0;
509     jets[1] = x1;
510     jets[2] = x2;
511     jets[3] = x3;
512     jets[4] = x4;
513     return cost_functor_(jets.get(), residuals);
514   }
515
516   template <typename JetT>
517   bool operator()(const JetT* x0,
518                   const JetT* x1,
519                   const JetT* x2,
520                   const JetT* x3,
521                   const JetT* x4,
522                   const JetT* x5,
523                   JetT* residuals) const {
524     CHECK_NE(N0, 0);
525     CHECK_NE(N1, 0);
526     CHECK_NE(N2, 0);
527     CHECK_NE(N3, 0);
528     CHECK_NE(N4, 0);
529     CHECK_NE(N5, 0);
530     CHECK_EQ(N6, 0);
531     CHECK_EQ(N7, 0);
532     CHECK_EQ(N8, 0);
533     CHECK_EQ(N9, 0);
534     internal::FixedArray<const JetT*> jets(6);
535     jets[0] = x0;
536     jets[1] = x1;
537     jets[2] = x2;
538     jets[3] = x3;
539     jets[4] = x4;
540     jets[5] = x5;
541     return cost_functor_(jets.get(), residuals);
542   }
543
544   template <typename JetT>
545   bool operator()(const JetT* x0,
546                   const JetT* x1,
547                   const JetT* x2,
548                   const JetT* x3,
549                   const JetT* x4,
550                   const JetT* x5,
551                   const JetT* x6,
552                   JetT* residuals) const {
553     CHECK_NE(N0, 0);
554     CHECK_NE(N1, 0);
555     CHECK_NE(N2, 0);
556     CHECK_NE(N3, 0);
557     CHECK_NE(N4, 0);
558     CHECK_NE(N5, 0);
559     CHECK_NE(N6, 0);
560     CHECK_EQ(N7, 0);
561     CHECK_EQ(N8, 0);
562     CHECK_EQ(N9, 0);
563     internal::FixedArray<const JetT*> jets(7);
564     jets[0] = x0;
565     jets[1] = x1;
566     jets[2] = x2;
567     jets[3] = x3;
568     jets[4] = x4;
569     jets[5] = x5;
570     jets[6] = x6;
571     return cost_functor_(jets.get(), residuals);
572   }
573
574   template <typename JetT>
575   bool operator()(const JetT* x0,
576                   const JetT* x1,
577                   const JetT* x2,
578                   const JetT* x3,
579                   const JetT* x4,
580                   const JetT* x5,
581                   const JetT* x6,
582                   const JetT* x7,
583                   JetT* residuals) const {
584     CHECK_NE(N0, 0);
585     CHECK_NE(N1, 0);
586     CHECK_NE(N2, 0);
587     CHECK_NE(N3, 0);
588     CHECK_NE(N4, 0);
589     CHECK_NE(N5, 0);
590     CHECK_NE(N6, 0);
591     CHECK_NE(N7, 0);
592     CHECK_EQ(N8, 0);
593     CHECK_EQ(N9, 0);
594     internal::FixedArray<const JetT*> jets(8);
595     jets[0] = x0;
596     jets[1] = x1;
597     jets[2] = x2;
598     jets[3] = x3;
599     jets[4] = x4;
600     jets[5] = x5;
601     jets[6] = x6;
602     jets[7] = x7;
603     return cost_functor_(jets.get(), residuals);
604   }
605
606   template <typename JetT>
607   bool operator()(const JetT* x0,
608                   const JetT* x1,
609                   const JetT* x2,
610                   const JetT* x3,
611                   const JetT* x4,
612                   const JetT* x5,
613                   const JetT* x6,
614                   const JetT* x7,
615                   const JetT* x8,
616                   JetT* residuals) const {
617     CHECK_NE(N0, 0);
618     CHECK_NE(N1, 0);
619     CHECK_NE(N2, 0);
620     CHECK_NE(N3, 0);
621     CHECK_NE(N4, 0);
622     CHECK_NE(N5, 0);
623     CHECK_NE(N6, 0);
624     CHECK_NE(N7, 0);
625     CHECK_NE(N8, 0);
626     CHECK_EQ(N9, 0);
627     internal::FixedArray<const JetT*> jets(9);
628     jets[0] = x0;
629     jets[1] = x1;
630     jets[2] = x2;
631     jets[3] = x3;
632     jets[4] = x4;
633     jets[5] = x5;
634     jets[6] = x6;
635     jets[7] = x7;
636     jets[8] = x8;
637     return cost_functor_(jets.get(), residuals);
638   }
639
640   template <typename JetT>
641   bool operator()(const JetT* x0,
642                   const JetT* x1,
643                   const JetT* x2,
644                   const JetT* x3,
645                   const JetT* x4,
646                   const JetT* x5,
647                   const JetT* x6,
648                   const JetT* x7,
649                   const JetT* x8,
650                   const JetT* x9,
651                   JetT* residuals) const {
652     CHECK_NE(N0, 0);
653     CHECK_NE(N1, 0);
654     CHECK_NE(N2, 0);
655     CHECK_NE(N3, 0);
656     CHECK_NE(N4, 0);
657     CHECK_NE(N5, 0);
658     CHECK_NE(N6, 0);
659     CHECK_NE(N7, 0);
660     CHECK_NE(N8, 0);
661     CHECK_NE(N9, 0);
662     internal::FixedArray<const JetT*> jets(10);
663     jets[0] = x0;
664     jets[1] = x1;
665     jets[2] = x2;
666     jets[3] = x3;
667     jets[4] = x4;
668     jets[5] = x5;
669     jets[6] = x6;
670     jets[7] = x7;
671     jets[8] = x8;
672     jets[9] = x9;
673     return cost_functor_(jets.get(), residuals);
674   }
675
676  private:
677   DynamicCostFunctionToFunctor cost_functor_;
678 };
679
680 }  // namespace ceres
681
682 #endif  // CERES_PUBLIC_COST_FUNCTION_TO_FUNCTOR_H_