g2o
Loading...
Searching...
No Matches
jet.h
Go to the documentation of this file.
1// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2019 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: keir@google.com (Keir Mierle)
30//
31// A simple implementation of N-dimensional dual numbers, for automatically
32// computing exact derivatives of functions.
33//
34// While a complete treatment of the mechanics of automatic differentiation is
35// beyond the scope of this header (see
36// http://en.wikipedia.org/wiki/Automatic_differentiation for details), the
37// basic idea is to extend normal arithmetic with an extra element, "e," often
38// denoted with the greek symbol epsilon, such that e != 0 but e^2 = 0. Dual
39// numbers are extensions of the real numbers analogous to complex numbers:
40// whereas complex numbers augment the reals by introducing an imaginary unit i
41// such that i^2 = -1, dual numbers introduce an "infinitesimal" unit e such
42// that e^2 = 0. Dual numbers have two components: the "real" component and the
43// "infinitesimal" component, generally written as x + y*e. Surprisingly, this
44// leads to a convenient method for computing exact derivatives without needing
45// to manipulate complicated symbolic expressions.
46//
47// For example, consider the function
48//
49// f(x) = x^2 ,
50//
51// evaluated at 10. Using normal arithmetic, f(10) = 100, and df/dx(10) = 20.
52// Next, argument 10 with an infinitesimal to get:
53//
54// f(10 + e) = (10 + e)^2
55// = 100 + 2 * 10 * e + e^2
56// = 100 + 20 * e -+-
57// -- |
58// | +--- This is zero, since e^2 = 0
59// |
60// +----------------- This is df/dx!
61//
62// Note that the derivative of f with respect to x is simply the infinitesimal
63// component of the value of f(x + e). So, in order to take the derivative of
64// any function, it is only necessary to replace the numeric "object" used in
65// the function with one extended with infinitesimals. The class Jet, defined in
66// this header, is one such example of this, where substitution is done with
67// templates.
68//
69// To handle derivatives of functions taking multiple arguments, different
70// infinitesimals are used, one for each variable to take the derivative of. For
71// example, consider a scalar function of two scalar parameters x and y:
72//
73// f(x, y) = x^2 + x * y
74//
75// Following the technique above, to compute the derivatives df/dx and df/dy for
76// f(1, 3) involves doing two evaluations of f, the first time replacing x with
77// x + e, the second time replacing y with y + e.
78//
79// For df/dx:
80//
81// f(1 + e, y) = (1 + e)^2 + (1 + e) * 3
82// = 1 + 2 * e + 3 + 3 * e
83// = 4 + 5 * e
84//
85// --> df/dx = 5
86//
87// For df/dy:
88//
89// f(1, 3 + e) = 1^2 + 1 * (3 + e)
90// = 1 + 3 + e
91// = 4 + e
92//
93// --> df/dy = 1
94//
95// To take the gradient of f with the implementation of dual numbers ("jets") in
96// this file, it is necessary to create a single jet type which has components
97// for the derivative in x and y, and passing them to a templated version of f:
98//
99// template<typename T>
100// T f(const T &x, const T &y) {
101// return x * x + x * y;
102// }
103//
104// // The "2" means there should be 2 dual number components.
105// // It computes the partial derivative at x=10, y=20.
106// Jet<double, 2> x(10, 0); // Pick the 0th dual number for x.
107// Jet<double, 2> y(20, 1); // Pick the 1st dual number for y.
108// Jet<double, 2> z = f(x, y);
109//
110// LOG(INFO) << "df/dx = " << z.v[0]
111// << "df/dy = " << z.v[1];
112//
113// Most users should not use Jet objects directly; a wrapper around Jet objects,
114// which makes computing the derivative, gradient, or jacobian of templated
115// functors simple, is in autodiff.h. Even autodiff.h should not be used
116// directly; instead autodiff_cost_function.h is typically the file of interest.
117//
118// For the more mathematically inclined, this file implements first-order
119// "jets". A 1st order jet is an element of the ring
120//
121// T[N] = T[t_1, ..., t_N] / (t_1, ..., t_N)^2
122//
123// which essentially means that each jet consists of a "scalar" value 'a' from T
124// and a 1st order perturbation vector 'v' of length N:
125//
126// x = a + \sum_i v[i] t_i
127//
128// A shorthand is to write an element as x = a + u, where u is the perturbation.
129// Then, the main point about the arithmetic of jets is that the product of
130// perturbations is zero:
131//
132// (a + u) * (b + v) = ab + av + bu + uv
133// = ab + (av + bu) + 0
134//
135// which is what operator* implements below. Addition is simpler:
136//
137// (a + u) + (b + v) = (a + b) + (u + v).
138//
139// The only remaining question is how to evaluate the function of a jet, for
140// which we use the chain rule:
141//
142// f(a + u) = f(a) + f'(a) u
143//
144// where f'(a) is the (scalar) derivative of f at a.
145//
146// By pushing these things through sufficiently and suitably templated
147// functions, we can do automatic differentiation. Just be sure to turn on
148// function inlining and common-subexpression elimination, or it will be very
149// slow!
150//
151// WARNING: Most Ceres users should not directly include this file or know the
152// details of how jets work. Instead the suggested method for automatic
153// derivatives is to use autodiff_cost_function.h, which is a wrapper around
154// both jets.h and autodiff.h to make taking derivatives of cost functions for
155// use in Ceres easier.
156
157#ifndef G2O_CERES_PUBLIC_JET_H_
158#define G2O_CERES_PUBLIC_JET_H_
159
160#include <cmath>
161#include <iosfwd>
162#include <iostream> // NOLINT
163#include <limits>
164#include <string>
165
166#include "Eigen/Core"
167
168namespace g2o {
169namespace ceres {
170
171template <typename T, int N>
172struct Jet {
173 enum { DIMENSION = N };
174 typedef T Scalar;
175
176 // Default-construct "a" because otherwise this can lead to false errors about
177 // uninitialized uses when other classes relying on default constructed T
178 // (where T is a Jet<T, N>). This usually only happens in opt mode. Note that
179 // the C++ standard mandates that e.g. default constructed doubles are
180 // initialized to 0.0; see sections 8.5 of the C++03 standard.
181 Jet() : a() { v.setConstant(Scalar()); }
182
183 // Constructor from scalar: a + 0.
184 explicit Jet(const T& value) {
185 a = value;
186 v.setConstant(Scalar());
187 }
188
189 // Constructor from scalar plus variable: a + t_i.
190 Jet(const T& value, int k) {
191 a = value;
192 v.setConstant(Scalar());
193 v[k] = T(1.0);
194 }
195
196 // Constructor from scalar and vector part
197 // The use of Eigen::DenseBase allows Eigen expressions
198 // to be passed in without being fully evaluated until
199 // they are assigned to v
200 template <typename Derived>
201 EIGEN_STRONG_INLINE Jet(const T& a, const Eigen::DenseBase<Derived>& v)
202 : a(a), v(v) {}
203
204 // Compound operators
206 *this = *this + y;
207 return *this;
208 }
209
211 *this = *this - y;
212 return *this;
213 }
214
216 *this = *this * y;
217 return *this;
218 }
219
221 *this = *this / y;
222 return *this;
223 }
224
225 // Compound with scalar operators.
226 Jet<T, N>& operator+=(const T& s) {
227 *this = *this + s;
228 return *this;
229 }
230
231 Jet<T, N>& operator-=(const T& s) {
232 *this = *this - s;
233 return *this;
234 }
235
236 Jet<T, N>& operator*=(const T& s) {
237 *this = *this * s;
238 return *this;
239 }
240
241 Jet<T, N>& operator/=(const T& s) {
242 *this = *this / s;
243 return *this;
244 }
245
246 // The scalar part.
247 T a;
248
249 // The infinitesimal part.
250 Eigen::Matrix<T, N, 1> v;
251
252 // This struct needs to have an Eigen aligned operator new as it contains
253 // fixed-size Eigen types.
254 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
255};
256
257// Unary +
258template <typename T, int N>
259inline Jet<T, N> const& operator+(const Jet<T, N>& f) {
260 return f;
261}
262
263// TODO(keir): Try adding __attribute__((always_inline)) to these functions to
264// see if it causes a performance increase.
265
266// Unary -
267template <typename T, int N>
268inline Jet<T, N> operator-(const Jet<T, N>& f) {
269 return Jet<T, N>(-f.a, -f.v);
270}
271
272// Binary +
273template <typename T, int N>
274inline Jet<T, N> operator+(const Jet<T, N>& f, const Jet<T, N>& g) {
275 return Jet<T, N>(f.a + g.a, f.v + g.v);
276}
277
278// Binary + with a scalar: x + s
279template <typename T, int N>
280inline Jet<T, N> operator+(const Jet<T, N>& f, T s) {
281 return Jet<T, N>(f.a + s, f.v);
282}
283
284// Binary + with a scalar: s + x
285template <typename T, int N>
286inline Jet<T, N> operator+(T s, const Jet<T, N>& f) {
287 return Jet<T, N>(f.a + s, f.v);
288}
289
290// Binary -
291template <typename T, int N>
292inline Jet<T, N> operator-(const Jet<T, N>& f, const Jet<T, N>& g) {
293 return Jet<T, N>(f.a - g.a, f.v - g.v);
294}
295
296// Binary - with a scalar: x - s
297template <typename T, int N>
298inline Jet<T, N> operator-(const Jet<T, N>& f, T s) {
299 return Jet<T, N>(f.a - s, f.v);
300}
301
302// Binary - with a scalar: s - x
303template <typename T, int N>
304inline Jet<T, N> operator-(T s, const Jet<T, N>& f) {
305 return Jet<T, N>(s - f.a, -f.v);
306}
307
308// Binary *
309template <typename T, int N>
310inline Jet<T, N> operator*(const Jet<T, N>& f, const Jet<T, N>& g) {
311 return Jet<T, N>(f.a * g.a, f.a * g.v + f.v * g.a);
312}
313
314// Binary * with a scalar: x * s
315template <typename T, int N>
316inline Jet<T, N> operator*(const Jet<T, N>& f, T s) {
317 return Jet<T, N>(f.a * s, f.v * s);
318}
319
320// Binary * with a scalar: s * x
321template <typename T, int N>
322inline Jet<T, N> operator*(T s, const Jet<T, N>& f) {
323 return Jet<T, N>(f.a * s, f.v * s);
324}
325
326// Binary /
327template <typename T, int N>
328inline Jet<T, N> operator/(const Jet<T, N>& f, const Jet<T, N>& g) {
329 // This uses:
330 //
331 // a + u (a + u)(b - v) (a + u)(b - v)
332 // ----- = -------------- = --------------
333 // b + v (b + v)(b - v) b^2
334 //
335 // which holds because v*v = 0.
336 const T g_a_inverse = T(1.0) / g.a;
337 const T f_a_by_g_a = f.a * g_a_inverse;
338 return Jet<T, N>(f_a_by_g_a, (f.v - f_a_by_g_a * g.v) * g_a_inverse);
339}
340
341// Binary / with a scalar: s / x
342template <typename T, int N>
343inline Jet<T, N> operator/(T s, const Jet<T, N>& g) {
344 const T minus_s_g_a_inverse2 = -s / (g.a * g.a);
345 return Jet<T, N>(s / g.a, g.v * minus_s_g_a_inverse2);
346}
347
348// Binary / with a scalar: x / s
349template <typename T, int N>
350inline Jet<T, N> operator/(const Jet<T, N>& f, T s) {
351 const T s_inverse = T(1.0) / s;
352 return Jet<T, N>(f.a * s_inverse, f.v * s_inverse);
353}
354
355// Binary comparison operators for both scalars and jets.
356#define G2O_CERES_DEFINE_JET_COMPARISON_OPERATOR(op) \
357 template <typename T, int N> \
358 inline bool operator op(const Jet<T, N>& f, const Jet<T, N>& g) { \
359 return f.a op g.a; \
360 } \
361 template <typename T, int N> \
362 inline bool operator op(const T& s, const Jet<T, N>& g) { \
363 return s op g.a; \
364 } \
365 template <typename T, int N> \
366 inline bool operator op(const Jet<T, N>& f, const T& s) { \
367 return f.a op s; \
368 }
375#undef G2O_CERES_DEFINE_JET_COMPARISON_OPERATOR
376
377// Pull some functions from namespace std.
378//
379// This is necessary because we want to use the same name (e.g. 'sqrt') for
380// double-valued and Jet-valued functions, but we are not allowed to put
381// Jet-valued functions inside namespace std.
382using std::abs;
383using std::acos;
384using std::asin;
385using std::atan;
386using std::atan2;
387using std::cbrt;
388using std::ceil;
389using std::cos;
390using std::cosh;
391using std::erf;
392using std::erfc;
393using std::exp;
394using std::exp2;
395using std::floor;
396using std::fmax;
397using std::fmin;
398using std::hypot;
399using std::isfinite;
400using std::isinf;
401using std::isnan;
402using std::isnormal;
403using std::log;
404using std::log2;
405using std::pow;
406using std::sin;
407using std::sinh;
408using std::sqrt;
409using std::tan;
410using std::tanh;
411
412// Legacy names from pre-C++11 days.
413// clang-format off
414inline bool IsFinite(double x) { return std::isfinite(x); }
415inline bool IsInfinite(double x) { return std::isinf(x); }
416inline bool IsNaN(double x) { return std::isnan(x); }
417inline bool IsNormal(double x) { return std::isnormal(x); }
418// clang-format on
419
420// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule.
421
422// abs(x + h) ~= x + h or -(x + h)
423template <typename T, int N>
424inline Jet<T, N> abs(const Jet<T, N>& f) {
425 return (f.a < T(0.0) ? -f : f);
426}
427
428// log(a + h) ~= log(a) + h / a
429template <typename T, int N>
430inline Jet<T, N> log(const Jet<T, N>& f) {
431 const T a_inverse = T(1.0) / f.a;
432 return Jet<T, N>(log(f.a), f.v * a_inverse);
433}
434
435// exp(a + h) ~= exp(a) + exp(a) h
436template <typename T, int N>
437inline Jet<T, N> exp(const Jet<T, N>& f) {
438 const T tmp = exp(f.a);
439 return Jet<T, N>(tmp, tmp * f.v);
440}
441
442// sqrt(a + h) ~= sqrt(a) + h / (2 sqrt(a))
443template <typename T, int N>
444inline Jet<T, N> sqrt(const Jet<T, N>& f) {
445 const T tmp = sqrt(f.a);
446 const T two_a_inverse = T(1.0) / (T(2.0) * tmp);
447 return Jet<T, N>(tmp, f.v * two_a_inverse);
448}
449
450// cos(a + h) ~= cos(a) - sin(a) h
451template <typename T, int N>
452inline Jet<T, N> cos(const Jet<T, N>& f) {
453 return Jet<T, N>(cos(f.a), -sin(f.a) * f.v);
454}
455
456// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
457template <typename T, int N>
458inline Jet<T, N> acos(const Jet<T, N>& f) {
459 const T tmp = -T(1.0) / sqrt(T(1.0) - f.a * f.a);
460 return Jet<T, N>(acos(f.a), tmp * f.v);
461}
462
463// sin(a + h) ~= sin(a) + cos(a) h
464template <typename T, int N>
465inline Jet<T, N> sin(const Jet<T, N>& f) {
466 return Jet<T, N>(sin(f.a), cos(f.a) * f.v);
467}
468
469// asin(a + h) ~= asin(a) + 1 / sqrt(1 - a^2) h
470template <typename T, int N>
471inline Jet<T, N> asin(const Jet<T, N>& f) {
472 const T tmp = T(1.0) / sqrt(T(1.0) - f.a * f.a);
473 return Jet<T, N>(asin(f.a), tmp * f.v);
474}
475
476// tan(a + h) ~= tan(a) + (1 + tan(a)^2) h
477template <typename T, int N>
478inline Jet<T, N> tan(const Jet<T, N>& f) {
479 const T tan_a = tan(f.a);
480 const T tmp = T(1.0) + tan_a * tan_a;
481 return Jet<T, N>(tan_a, tmp * f.v);
482}
483
484// atan(a + h) ~= atan(a) + 1 / (1 + a^2) h
485template <typename T, int N>
486inline Jet<T, N> atan(const Jet<T, N>& f) {
487 const T tmp = T(1.0) / (T(1.0) + f.a * f.a);
488 return Jet<T, N>(atan(f.a), tmp * f.v);
489}
490
491// sinh(a + h) ~= sinh(a) + cosh(a) h
492template <typename T, int N>
493inline Jet<T, N> sinh(const Jet<T, N>& f) {
494 return Jet<T, N>(sinh(f.a), cosh(f.a) * f.v);
495}
496
497// cosh(a + h) ~= cosh(a) + sinh(a) h
498template <typename T, int N>
499inline Jet<T, N> cosh(const Jet<T, N>& f) {
500 return Jet<T, N>(cosh(f.a), sinh(f.a) * f.v);
501}
502
503// tanh(a + h) ~= tanh(a) + (1 - tanh(a)^2) h
504template <typename T, int N>
505inline Jet<T, N> tanh(const Jet<T, N>& f) {
506 const T tanh_a = tanh(f.a);
507 const T tmp = T(1.0) - tanh_a * tanh_a;
508 return Jet<T, N>(tanh_a, tmp * f.v);
509}
510
511// The floor function should be used with extreme care as this operation will
512// result in a zero derivative which provides no information to the solver.
513//
514// floor(a + h) ~= floor(a) + 0
515template <typename T, int N>
516inline Jet<T, N> floor(const Jet<T, N>& f) {
517 return Jet<T, N>(floor(f.a));
518}
519
520// The ceil function should be used with extreme care as this operation will
521// result in a zero derivative which provides no information to the solver.
522//
523// ceil(a + h) ~= ceil(a) + 0
524template <typename T, int N>
525inline Jet<T, N> ceil(const Jet<T, N>& f) {
526 return Jet<T, N>(ceil(f.a));
527}
528
529// Some new additions to C++11:
530
531// cbrt(a + h) ~= cbrt(a) + h / (3 a ^ (2/3))
532template <typename T, int N>
533inline Jet<T, N> cbrt(const Jet<T, N>& f) {
534 const T derivative = T(1.0) / (T(3.0) * cbrt(f.a * f.a));
535 return Jet<T, N>(cbrt(f.a), f.v * derivative);
536}
537
538// exp2(x + h) = 2^(x+h) ~= 2^x + h*2^x*log(2)
539template <typename T, int N>
540inline Jet<T, N> exp2(const Jet<T, N>& f) {
541 const T tmp = exp2(f.a);
542 const T derivative = tmp * log(T(2));
543 return Jet<T, N>(tmp, f.v * derivative);
544}
545
546// log2(x + h) ~= log2(x) + h / (x * log(2))
547template <typename T, int N>
548inline Jet<T, N> log2(const Jet<T, N>& f) {
549 const T derivative = T(1.0) / (f.a * log(T(2)));
550 return Jet<T, N>(log2(f.a), f.v * derivative);
551}
552
553// Like sqrt(x^2 + y^2),
554// but acts to prevent underflow/overflow for small/large x/y.
555// Note that the function is non-smooth at x=y=0,
556// so the derivative is undefined there.
557template <typename T, int N>
558inline Jet<T, N> hypot(const Jet<T, N>& x, const Jet<T, N>& y) {
559 // d/da sqrt(a) = 0.5 / sqrt(a)
560 // d/dx x^2 + y^2 = 2x
561 // So by the chain rule:
562 // d/dx sqrt(x^2 + y^2) = 0.5 / sqrt(x^2 + y^2) * 2x = x / sqrt(x^2 + y^2)
563 // d/dy sqrt(x^2 + y^2) = y / sqrt(x^2 + y^2)
564 const T tmp = hypot(x.a, y.a);
565 return Jet<T, N>(tmp, x.a / tmp * x.v + y.a / tmp * y.v);
566}
567
568template <typename T, int N>
569inline Jet<T, N> fmax(const Jet<T, N>& x, const Jet<T, N>& y) {
570 return x < y ? y : x;
571}
572
573template <typename T, int N>
574inline Jet<T, N> fmin(const Jet<T, N>& x, const Jet<T, N>& y) {
575 return y < x ? y : x;
576}
577
578// erf is defined as an integral that cannot be expressed analytically
579// however, the derivative is trivial to compute
580// erf(x + h) = erf(x) + h * 2*exp(-x^2)/sqrt(pi)
581template <typename T, int N>
582inline Jet<T, N> erf(const Jet<T, N>& x) {
583 return Jet<T, N>(erf(x.a), x.v * M_2_SQRTPI * exp(-x.a * x.a));
584}
585
586// erfc(x) = 1-erf(x)
587// erfc(x + h) = erfc(x) + h * (-2*exp(-x^2)/sqrt(pi))
588template <typename T, int N>
589inline Jet<T, N> erfc(const Jet<T, N>& x) {
590 return Jet<T, N>(erfc(x.a), -x.v * M_2_SQRTPI * exp(-x.a * x.a));
591}
592
593// Bessel functions of the first kind with integer order equal to 0, 1, n.
594//
595// Microsoft has deprecated the j[0,1,n]() POSIX Bessel functions in favour of
596// _j[0,1,n](). Where available on MSVC, use _j[0,1,n]() to avoid deprecated
597// function errors in client code (the specific warning is suppressed when
598// Ceres itself is built).
599inline double BesselJ0(double x) {
600#if defined(G2O_CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
601 return _j0(x);
602#else
603 return j0(x);
604#endif
605}
606inline double BesselJ1(double x) {
607#if defined(G2O_CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
608 return _j1(x);
609#else
610 return j1(x);
611#endif
612}
613inline double BesselJn(int n, double x) {
614#if defined(G2O_CERES_MSVC_USE_UNDERSCORE_PREFIXED_BESSEL_FUNCTIONS)
615 return _jn(n, x);
616#else
617 return jn(n, x);
618#endif
619}
620
621// For the formulae of the derivatives of the Bessel functions see the book:
622// Olver, Lozier, Boisvert, Clark, NIST Handbook of Mathematical Functions,
623// Cambridge University Press 2010.
624//
625// Formulae are also available at http://dlmf.nist.gov
626
627// See formula http://dlmf.nist.gov/10.6#E3
628// j0(a + h) ~= j0(a) - j1(a) h
629template <typename T, int N>
630inline Jet<T, N> BesselJ0(const Jet<T, N>& f) {
631 return Jet<T, N>(BesselJ0(f.a), -BesselJ1(f.a) * f.v);
632}
633
634// See formula http://dlmf.nist.gov/10.6#E1
635// j1(a + h) ~= j1(a) + 0.5 ( j0(a) - j2(a) ) h
636template <typename T, int N>
637inline Jet<T, N> BesselJ1(const Jet<T, N>& f) {
638 return Jet<T, N>(BesselJ1(f.a),
639 T(0.5) * (BesselJ0(f.a) - BesselJn(2, f.a)) * f.v);
640}
641
642// See formula http://dlmf.nist.gov/10.6#E1
643// j_n(a + h) ~= j_n(a) + 0.5 ( j_{n-1}(a) - j_{n+1}(a) ) h
644template <typename T, int N>
645inline Jet<T, N> BesselJn(int n, const Jet<T, N>& f) {
646 return Jet<T, N>(
647 BesselJn(n, f.a),
648 T(0.5) * (BesselJn(n - 1, f.a) - BesselJn(n + 1, f.a)) * f.v);
649}
650
651// Jet Classification. It is not clear what the appropriate semantics are for
652// these classifications. This picks that std::isfinite and std::isnormal are
653// "all" operations, i.e. all elements of the jet must be finite for the jet
654// itself to be finite (or normal). For IsNaN and IsInfinite, the answer is less
655// clear. This takes a "any" approach for IsNaN and IsInfinite such that if any
656// part of a jet is nan or inf, then the entire jet is nan or inf. This leads
657// to strange situations like a jet can be both IsInfinite and IsNaN, but in
658// practice the "any" semantics are the most useful for e.g. checking that
659// derivatives are sane.
660
661// The jet is finite if all parts of the jet are finite.
662template <typename T, int N>
663inline bool isfinite(const Jet<T, N>& f) {
664 // Branchless implementation. This is more efficient for the false-case and
665 // works with the codegen system.
666 auto result = isfinite(f.a);
667 for (int i = 0; i < N; ++i) {
668 result = result & isfinite(f.v[i]);
669 }
670 return result;
671}
672
673// The jet is infinite if any part of the Jet is infinite.
674template <typename T, int N>
675inline bool isinf(const Jet<T, N>& f) {
676 auto result = isinf(f.a);
677 for (int i = 0; i < N; ++i) {
678 result = result | isinf(f.v[i]);
679 }
680 return result;
681}
682
683// The jet is NaN if any part of the jet is NaN.
684template <typename T, int N>
685inline bool isnan(const Jet<T, N>& f) {
686 auto result = isnan(f.a);
687 for (int i = 0; i < N; ++i) {
688 result = result | isnan(f.v[i]);
689 }
690 return result;
691}
692
693// The jet is normal if all parts of the jet are normal.
694template <typename T, int N>
695inline bool isnormal(const Jet<T, N>& f) {
696 auto result = isnormal(f.a);
697 for (int i = 0; i < N; ++i) {
698 result = result & isnormal(f.v[i]);
699 }
700 return result;
701}
702
703// Legacy functions from the pre-C++11 days.
704template <typename T, int N>
705inline bool IsFinite(const Jet<T, N>& f) {
706 return isfinite(f);
707}
708
709template <typename T, int N>
710inline bool IsNaN(const Jet<T, N>& f) {
711 return isnan(f);
712}
713
714template <typename T, int N>
715inline bool IsNormal(const Jet<T, N>& f) {
716 return isnormal(f);
717}
718
719// The jet is infinite if any part of the jet is infinite.
720template <typename T, int N>
721inline bool IsInfinite(const Jet<T, N>& f) {
722 return isinf(f);
723}
724
725// atan2(b + db, a + da) ~= atan2(b, a) + (- b da + a db) / (a^2 + b^2)
726//
727// In words: the rate of change of theta is 1/r times the rate of
728// change of (x, y) in the positive angular direction.
729template <typename T, int N>
730inline Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
731 // Note order of arguments:
732 //
733 // f = a + da
734 // g = b + db
735
736 T const tmp = T(1.0) / (f.a * f.a + g.a * g.a);
737 return Jet<T, N>(atan2(g.a, f.a), tmp * (-g.a * f.v + f.a * g.v));
738}
739
740// pow -- base is a differentiable function, exponent is a constant.
741// (a+da)^p ~= a^p + p*a^(p-1) da
742template <typename T, int N>
743inline Jet<T, N> pow(const Jet<T, N>& f, double g) {
744 T const tmp = g * pow(f.a, g - T(1.0));
745 return Jet<T, N>(pow(f.a, g), tmp * f.v);
746}
747
748// pow -- base is a constant, exponent is a differentiable function.
749// We have various special cases, see the comment for pow(Jet, Jet) for
750// analysis:
751//
752// 1. For f > 0 we have: (f)^(g + dg) ~= f^g + f^g log(f) dg
753//
754// 2. For f == 0 and g > 0 we have: (f)^(g + dg) ~= f^g
755//
756// 3. For f < 0 and integer g we have: (f)^(g + dg) ~= f^g but if dg
757// != 0, the derivatives are not defined and we return NaN.
758
759template <typename T, int N>
760inline Jet<T, N> pow(T f, const Jet<T, N>& g) {
761 Jet<T, N> result;
762
763 if (f == T(0) && g.a > T(0)) {
764 // Handle case 2.
765 result = Jet<T, N>(T(0.0));
766 } else {
767 if (f < 0 && g.a == floor(g.a)) { // Handle case 3.
768 result = Jet<T, N>(pow(f, g.a));
769 for (int i = 0; i < N; i++) {
770 if (g.v[i] != T(0.0)) {
771 // Return a NaN when g.v != 0.
772 result.v[i] = std::numeric_limits<T>::quiet_NaN();
773 }
774 }
775 } else {
776 // Handle case 1.
777 T const tmp = pow(f, g.a);
778 result = Jet<T, N>(tmp, log(f) * tmp * g.v);
779 }
780 }
781
782 return result;
783}
784
785// pow -- both base and exponent are differentiable functions. This has a
786// variety of special cases that require careful handling.
787//
788// 1. For f > 0:
789// (f + df)^(g + dg) ~= f^g + f^(g - 1) * (g * df + f * log(f) * dg)
790// The numerical evaluation of f * log(f) for f > 0 is well behaved, even for
791// extremely small values (e.g. 1e-99).
792//
793// 2. For f == 0 and g > 1: (f + df)^(g + dg) ~= 0
794// This cases is needed because log(0) can not be evaluated in the f > 0
795// expression. However the function f*log(f) is well behaved around f == 0
796// and its limit as f-->0 is zero.
797//
798// 3. For f == 0 and g == 1: (f + df)^(g + dg) ~= 0 + df
799//
800// 4. For f == 0 and 0 < g < 1: The value is finite but the derivatives are not.
801//
802// 5. For f == 0 and g < 0: The value and derivatives of f^g are not finite.
803//
804// 6. For f == 0 and g == 0: The C standard incorrectly defines 0^0 to be 1
805// "because there are applications that can exploit this definition". We
806// (arbitrarily) decree that derivatives here will be nonfinite, since that
807// is consistent with the behavior for f == 0, g < 0 and 0 < g < 1.
808// Practically any definition could have been justified because mathematical
809// consistency has been lost at this point.
810//
811// 7. For f < 0, g integer, dg == 0: (f + df)^(g + dg) ~= f^g + g * f^(g - 1) df
812// This is equivalent to the case where f is a differentiable function and g
813// is a constant (to first order).
814//
815// 8. For f < 0, g integer, dg != 0: The value is finite but the derivatives are
816// not, because any change in the value of g moves us away from the point
817// with a real-valued answer into the region with complex-valued answers.
818//
819// 9. For f < 0, g noninteger: The value and derivatives of f^g are not finite.
820
821template <typename T, int N>
822inline Jet<T, N> pow(const Jet<T, N>& f, const Jet<T, N>& g) {
823 Jet<T, N> result;
824
825 if (f.a == T(0) && g.a >= T(1)) {
826 // Handle cases 2 and 3.
827 if (g.a > T(1)) {
828 result = Jet<T, N>(T(0.0));
829 } else {
830 result = f;
831 }
832
833 } else {
834 if (f.a < T(0) && g.a == floor(g.a)) {
835 // Handle cases 7 and 8.
836 T const tmp = g.a * pow(f.a, g.a - T(1.0));
837 result = Jet<T, N>(pow(f.a, g.a), tmp * f.v);
838 for (int i = 0; i < N; i++) {
839 if (g.v[i] != T(0.0)) {
840 // Return a NaN when g.v != 0.
841 result.v[i] = T(std::numeric_limits<double>::quiet_NaN());
842 }
843 }
844 } else {
845 // Handle the remaining cases. For cases 4,5,6,9 we allow the log()
846 // function to generate -HUGE_VAL or NaN, since those cases result in a
847 // nonfinite derivative.
848 T const tmp1 = pow(f.a, g.a);
849 T const tmp2 = g.a * pow(f.a, g.a - T(1.0));
850 T const tmp3 = tmp1 * log(f.a);
851 result = Jet<T, N>(tmp1, tmp2 * f.v + tmp3 * g.v);
852 }
853 }
854
855 return result;
856}
857
858// Note: This has to be in the ceres namespace for argument dependent lookup to
859// function correctly. Otherwise statements like CHECK_LE(x, 2.0) fail with
860// strange compile errors.
861template <typename T, int N>
862inline std::ostream& operator<<(std::ostream& s, const Jet<T, N>& z) {
863 s << "[" << z.a << " ; ";
864 for (int i = 0; i < N; ++i) {
865 s << z.v[i];
866 if (i != N - 1) {
867 s << ", ";
868 }
869 }
870 s << "]";
871 return s;
872}
873} // namespace ceres
874} // namespace g2o
875
876namespace std {
877// clang-format off
878template <typename T, int N>
879struct numeric_limits<g2o::ceres::Jet<T, N>> {
880 static constexpr bool is_specialized = true; // NOLINT
881 static constexpr bool is_signed = std::numeric_limits<T>::is_signed; // NOLINT
882 static constexpr bool is_integer = std::numeric_limits<T>::is_integer; // NOLINT
883 static constexpr bool is_exact = std::numeric_limits<T>::is_exact; // NOLINT
884 static constexpr bool has_infinity = std::numeric_limits<T>::has_infinity; // NOLINT
885 static constexpr bool has_quiet_NaN = std::numeric_limits<T>::has_quiet_NaN; // NOLINT
886 static constexpr bool has_signaling_NaN = std::numeric_limits<T>::has_signaling_NaN; // NOLINT
887 static constexpr bool is_iec559 = std::numeric_limits<T>::is_iec559; // NOLINT
888 static constexpr bool is_bounded = std::numeric_limits<T>::is_bounded; // NOLINT
889 static constexpr bool is_modulo = std::numeric_limits<T>::is_modulo; // NOLINT
890
891 static constexpr std::float_denorm_style has_denorm = std::numeric_limits<T>::has_denorm; // NOLINT
892 static constexpr std::float_round_style round_style = std::numeric_limits<T>::round_style; // NOLINT
893
894 static constexpr int digits = std::numeric_limits<T>::digits; // NOLINT
895 static constexpr int digits10 = std::numeric_limits<T>::digits10; // NOLINT
896 static constexpr int max_digits10 = std::numeric_limits<T>::max_digits10; // NOLINT
897 static constexpr int radix = std::numeric_limits<T>::radix; // NOLINT
898 static constexpr int min_exponent = std::numeric_limits<T>::min_exponent; // NOLINT
899 static constexpr int min_exponent10 = std::numeric_limits<T>::max_exponent10; // NOLINT
900 static constexpr int max_exponent = std::numeric_limits<T>::max_exponent; // NOLINT
901 static constexpr int max_exponent10 = std::numeric_limits<T>::max_exponent10; // NOLINT
902 static constexpr bool traps = std::numeric_limits<T>::traps; // NOLINT
903 static constexpr bool tinyness_before = std::numeric_limits<T>::tinyness_before; // NOLINT
904
905 static constexpr g2o::ceres::Jet<T, N> min() noexcept {
906 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::min());
907 }
908 static constexpr g2o::ceres::Jet<T, N> lowest() noexcept {
909 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::lowest());
910 }
911 static constexpr g2o::ceres::Jet<T, N> epsilon() noexcept {
912 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::epsilon());
913 }
914 static constexpr g2o::ceres::Jet<T, N> round_error() noexcept {
915 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::round_error());
916 }
917 static constexpr g2o::ceres::Jet<T, N> infinity() noexcept {
918 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::infinity());
919 }
920 static constexpr g2o::ceres::Jet<T, N> quiet_NaN() noexcept {
921 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::quiet_NaN());
922 }
923 static constexpr g2o::ceres::Jet<T, N> signaling_NaN() noexcept {
924 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::signaling_NaN());
925 }
926 static constexpr g2o::ceres::Jet<T, N> denorm_min() noexcept {
927 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::denorm_min());
928 }
929
930 static constexpr g2o::ceres::Jet<T, N> max() noexcept {
931 return g2o::ceres::Jet<T, N>(std::numeric_limits<T>::max());
932 }
933};
934// clang-format on
935
936} // namespace std
937
938namespace Eigen {
939
940// Creating a specialization of NumTraits enables placing Jet objects inside
941// Eigen arrays, getting all the goodness of Eigen combined with autodiff.
942template <typename T, int N>
943struct NumTraits<g2o::ceres::Jet<T, N>> {
948
950 return g2o::ceres::Jet<T, N>(1e-12);
951 }
952
953 static inline Real epsilon() {
954 return Real(std::numeric_limits<T>::epsilon());
955 }
956
957 static inline int digits10() { return NumTraits<T>::digits10(); }
958
959 enum {
960 IsComplex = 0, // NOLINT
961 IsInteger = 0, // NOLINT
962 IsSigned, // NOLINT
963 ReadCost = 1, // NOLINT
964 AddCost = 1, // NOLINT
965 // For Jet types, multiplication is more expensive than addition.
966 MulCost = 3, // NOLINT
967 HasFloatingPoint = 1, // NOLINT
968 RequireInitialization = 1 // NOLINT
969 };
970
971 template <bool Vectorized>
972 struct Div {
973 enum {
974#if defined(EIGEN_VECTORIZE_AVX)
975 AVX = true, // NOLINT
976#else
977 AVX = false, // NOLINT
978#endif
979
980 // Assuming that for Jets, division is as expensive as
981 // multiplication.
982 Cost = 3 // NOLINT
983 };
984 };
985
986 static inline Real highest() { return Real(std::numeric_limits<T>::max()); }
987 static inline Real lowest() { return Real(-std::numeric_limits<T>::max()); }
988};
989
990// Specifying the return type of binary operations between Jets and scalar types
991// allows you to perform matrix/array operations with Eigen matrices and arrays
992// such as addition, subtraction, multiplication, and division where one Eigen
993// matrix/array is of type Jet and the other is a scalar type. This improves
994// performance by using the optimized scalar-to-Jet binary operations but
995// is only available on Eigen versions >= 3.3
996template <typename BinaryOp, typename T, int N>
997struct ScalarBinaryOpTraits<g2o::ceres::Jet<T, N>, T, BinaryOp> {
999};
1000template <typename BinaryOp, typename T, int N>
1001struct ScalarBinaryOpTraits<T, g2o::ceres::Jet<T, N>, BinaryOp> {
1003};
1004
1005} // namespace Eigen
1006
1007#endif // G2O_CERES_PUBLIC_JET_H_
#define G2O_CERES_DEFINE_JET_COMPARISON_OPERATOR(op)
Definition jet.h:356
Definition jet.h:938
Jet< T, N > cosh(const Jet< T, N > &f)
Definition jet.h:499
Jet< T, N > pow(const Jet< T, N > &f, double g)
Definition jet.h:743
bool isnormal(const Jet< T, N > &f)
Definition jet.h:695
Jet< T, N > fmax(const Jet< T, N > &x, const Jet< T, N > &y)
Definition jet.h:569
Jet< T, N > operator/(const Jet< T, N > &f, const Jet< T, N > &g)
Definition jet.h:328
Jet< T, N > tan(const Jet< T, N > &f)
Definition jet.h:478
Jet< T, N > cos(const Jet< T, N > &f)
Definition jet.h:452
bool IsNormal(double x)
Definition jet.h:417
Jet< T, N > erf(const Jet< T, N > &x)
Definition jet.h:582
Jet< T, N > sin(const Jet< T, N > &f)
Definition jet.h:465
bool IsNaN(double x)
Definition jet.h:416
Jet< T, N > operator*(const Jet< T, N > &f, const Jet< T, N > &g)
Definition jet.h:310
bool isfinite(const Jet< T, N > &f)
Definition jet.h:663
Jet< T, N > sinh(const Jet< T, N > &f)
Definition jet.h:493
Jet< T, N > floor(const Jet< T, N > &f)
Definition jet.h:516
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition jet.h:444
Jet< T, N > atan2(const Jet< T, N > &g, const Jet< T, N > &f)
Definition jet.h:730
double BesselJ1(double x)
Definition jet.h:606
Jet< T, N > log(const Jet< T, N > &f)
Definition jet.h:430
Jet< T, N > hypot(const Jet< T, N > &x, const Jet< T, N > &y)
Definition jet.h:558
double BesselJ0(double x)
Definition jet.h:599
Jet< T, N > ceil(const Jet< T, N > &f)
Definition jet.h:525
Jet< T, N > exp(const Jet< T, N > &f)
Definition jet.h:437
Jet< T, N > exp2(const Jet< T, N > &f)
Definition jet.h:540
Jet< T, N > log2(const Jet< T, N > &f)
Definition jet.h:548
std::ostream & operator<<(std::ostream &s, const Jet< T, N > &z)
Definition jet.h:862
Jet< T, N > const & operator+(const Jet< T, N > &f)
Definition jet.h:259
Jet< T, N > tanh(const Jet< T, N > &f)
Definition jet.h:505
Jet< T, N > atan(const Jet< T, N > &f)
Definition jet.h:486
Jet< T, N > abs(const Jet< T, N > &f)
Definition jet.h:424
bool IsFinite(double x)
Definition jet.h:414
bool isnan(const Jet< T, N > &f)
Definition jet.h:685
Jet< T, N > operator-(const Jet< T, N > &f)
Definition jet.h:268
bool IsInfinite(double x)
Definition jet.h:415
Jet< T, N > cbrt(const Jet< T, N > &f)
Definition jet.h:533
Jet< T, N > acos(const Jet< T, N > &f)
Definition jet.h:458
Jet< T, N > erfc(const Jet< T, N > &x)
Definition jet.h:589
bool isinf(const Jet< T, N > &f)
Definition jet.h:675
Jet< T, N > fmin(const Jet< T, N > &x, const Jet< T, N > &y)
Definition jet.h:574
Jet< T, N > asin(const Jet< T, N > &f)
Definition jet.h:471
double BesselJn(int n, double x)
Definition jet.h:613
Definition jet.h:876
static g2o::ceres::Jet< T, N > dummy_precision()
Definition jet.h:949
EIGEN_STRONG_INLINE Jet(const T &a, const Eigen::DenseBase< Derived > &v)
Definition jet.h:201
Jet< T, N > & operator/=(const T &s)
Definition jet.h:241
Jet< T, N > & operator*=(const T &s)
Definition jet.h:236
Jet< T, N > & operator+=(const Jet< T, N > &y)
Definition jet.h:205
Jet< T, N > & operator/=(const Jet< T, N > &y)
Definition jet.h:220
Jet(const T &value)
Definition jet.h:184
Jet< T, N > & operator-=(const Jet< T, N > &y)
Definition jet.h:210
Jet< T, N > & operator-=(const T &s)
Definition jet.h:231
Eigen::Matrix< T, N, 1 > v
Definition jet.h:250
Jet< T, N > & operator*=(const Jet< T, N > &y)
Definition jet.h:215
Jet(const T &value, int k)
Definition jet.h:190
Jet< T, N > & operator+=(const T &s)
Definition jet.h:226
static constexpr g2o::ceres::Jet< T, N > lowest() noexcept
Definition jet.h:908
static constexpr g2o::ceres::Jet< T, N > epsilon() noexcept
Definition jet.h:911
static constexpr g2o::ceres::Jet< T, N > denorm_min() noexcept
Definition jet.h:926
static constexpr g2o::ceres::Jet< T, N > max() noexcept
Definition jet.h:930
static constexpr g2o::ceres::Jet< T, N > signaling_NaN() noexcept
Definition jet.h:923
static constexpr g2o::ceres::Jet< T, N > infinity() noexcept
Definition jet.h:917
static constexpr g2o::ceres::Jet< T, N > quiet_NaN() noexcept
Definition jet.h:920
static constexpr g2o::ceres::Jet< T, N > min() noexcept
Definition jet.h:905
static constexpr g2o::ceres::Jet< T, N > round_error() noexcept
Definition jet.h:914