blob: da49f32019f3dc1e7ecc2175715f618bf86e97ee [file] [log] [blame]
Austin Schuh70cc9552019-01-21 19:46:48 -08001// Ceres Solver - A fast non-linear least squares minimizer
Austin Schuh1d1e6ea2020-12-23 21:56:30 -08002// Copyright 2019 Google Inc. All rights reserved.
Austin Schuh70cc9552019-01-21 19:46:48 -08003// 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 CERES_PUBLIC_JET_H_
158#define 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#include "ceres/internal/port.h"
168
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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800181 Jet() : a() { v.setConstant(Scalar()); }
Austin Schuh70cc9552019-01-21 19:46:48 -0800182
183 // Constructor from scalar: a + 0.
184 explicit Jet(const T& value) {
185 a = value;
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800186 v.setConstant(Scalar());
Austin Schuh70cc9552019-01-21 19:46:48 -0800187 }
188
189 // Constructor from scalar plus variable: a + t_i.
190 Jet(const T& value, int k) {
191 a = value;
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800192 v.setConstant(Scalar());
Austin Schuh70cc9552019-01-21 19:46:48 -0800193 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800200 template <typename Derived>
201 EIGEN_STRONG_INLINE Jet(const T& a, const Eigen::DenseBase<Derived>& v)
202 : a(a), v(v) {}
Austin Schuh70cc9552019-01-21 19:46:48 -0800203
204 // Compound operators
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800205 Jet<T, N>& operator+=(const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800206 *this = *this + y;
207 return *this;
208 }
209
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800210 Jet<T, N>& operator-=(const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800211 *this = *this - y;
212 return *this;
213 }
214
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800215 Jet<T, N>& operator*=(const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800216 *this = *this * y;
217 return *this;
218 }
219
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800220 Jet<T, N>& operator/=(const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800221 *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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800250 Eigen::Matrix<T, N, 1> v;
Austin Schuh70cc9552019-01-21 19:46:48 -0800251
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800252 // This struct needs to have an Eigen aligned operator new as it contains
253 // fixed-size Eigen types.
254 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Austin Schuh70cc9552019-01-21 19:46:48 -0800255};
256
257// Unary +
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800258template <typename T, int N>
259inline Jet<T, N> const& operator+(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800260 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 -
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800267template <typename T, int N>
268inline Jet<T, N> operator-(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800269 return Jet<T, N>(-f.a, -f.v);
270}
271
272// Binary +
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800273template <typename T, int N>
274inline Jet<T, N> operator+(const Jet<T, N>& f, const Jet<T, N>& g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800275 return Jet<T, N>(f.a + g.a, f.v + g.v);
276}
277
278// Binary + with a scalar: x + s
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800279template <typename T, int N>
280inline Jet<T, N> operator+(const Jet<T, N>& f, T s) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800281 return Jet<T, N>(f.a + s, f.v);
282}
283
284// Binary + with a scalar: s + x
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800285template <typename T, int N>
286inline Jet<T, N> operator+(T s, const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800287 return Jet<T, N>(f.a + s, f.v);
288}
289
290// Binary -
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800291template <typename T, int N>
292inline Jet<T, N> operator-(const Jet<T, N>& f, const Jet<T, N>& g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800293 return Jet<T, N>(f.a - g.a, f.v - g.v);
294}
295
296// Binary - with a scalar: x - s
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800297template <typename T, int N>
298inline Jet<T, N> operator-(const Jet<T, N>& f, T s) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800299 return Jet<T, N>(f.a - s, f.v);
300}
301
302// Binary - with a scalar: s - x
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800303template <typename T, int N>
304inline Jet<T, N> operator-(T s, const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800305 return Jet<T, N>(s - f.a, -f.v);
306}
307
308// Binary *
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800309template <typename T, int N>
310inline Jet<T, N> operator*(const Jet<T, N>& f, const Jet<T, N>& g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800311 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800315template <typename T, int N>
316inline Jet<T, N> operator*(const Jet<T, N>& f, T s) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800317 return Jet<T, N>(f.a * s, f.v * s);
318}
319
320// Binary * with a scalar: s * x
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800321template <typename T, int N>
322inline Jet<T, N> operator*(T s, const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800323 return Jet<T, N>(f.a * s, f.v * s);
324}
325
326// Binary /
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800327template <typename T, int N>
328inline Jet<T, N> operator/(const Jet<T, N>& f, const Jet<T, N>& g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800329 // 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800342template <typename T, int N>
343inline Jet<T, N> operator/(T s, const Jet<T, N>& g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800344 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800349template <typename T, int N>
350inline Jet<T, N> operator/(const Jet<T, N>& f, T s) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800351 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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800356#define 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 }
369CERES_DEFINE_JET_COMPARISON_OPERATOR(<) // NOLINT
370CERES_DEFINE_JET_COMPARISON_OPERATOR(<=) // NOLINT
371CERES_DEFINE_JET_COMPARISON_OPERATOR(>) // NOLINT
372CERES_DEFINE_JET_COMPARISON_OPERATOR(>=) // NOLINT
373CERES_DEFINE_JET_COMPARISON_OPERATOR(==) // NOLINT
374CERES_DEFINE_JET_COMPARISON_OPERATOR(!=) // NOLINT
Austin Schuh70cc9552019-01-21 19:46:48 -0800375#undef 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;
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800391using std::erf;
392using std::erfc;
Austin Schuh70cc9552019-01-21 19:46:48 -0800393using 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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800413// clang-format off
414inline bool IsFinite(double x) { return std::isfinite(x); }
Austin Schuh70cc9552019-01-21 19:46:48 -0800415inline bool IsInfinite(double x) { return std::isinf(x); }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800416inline bool IsNaN(double x) { return std::isnan(x); }
417inline bool IsNormal(double x) { return std::isnormal(x); }
418// clang-format on
Austin Schuh70cc9552019-01-21 19:46:48 -0800419
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)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800423template <typename T, int N>
424inline Jet<T, N> abs(const Jet<T, N>& f) {
425 return (f.a < T(0.0) ? -f : f);
Austin Schuh70cc9552019-01-21 19:46:48 -0800426}
427
428// log(a + h) ~= log(a) + h / a
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800429template <typename T, int N>
430inline Jet<T, N> log(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800431 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800436template <typename T, int N>
437inline Jet<T, N> exp(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800438 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))
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800443template <typename T, int N>
444inline Jet<T, N> sqrt(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800445 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800451template <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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800454}
455
456// acos(a + h) ~= acos(a) - 1 / sqrt(1 - a^2) h
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800457template <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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800460 return Jet<T, N>(acos(f.a), tmp * f.v);
461}
462
463// sin(a + h) ~= sin(a) + cos(a) h
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800464template <typename T, int N>
465inline Jet<T, N> sin(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800466 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800470template <typename T, int N>
471inline Jet<T, N> asin(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800472 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800477template <typename T, int N>
478inline Jet<T, N> tan(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800479 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800485template <typename T, int N>
486inline Jet<T, N> atan(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800487 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800492template <typename T, int N>
493inline Jet<T, N> sinh(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800494 return Jet<T, N>(sinh(f.a), cosh(f.a) * f.v);
495}
496
497// cosh(a + h) ~= cosh(a) + sinh(a) h
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800498template <typename T, int N>
499inline Jet<T, N> cosh(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800500 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800504template <typename T, int N>
505inline Jet<T, N> tanh(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800506 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800515template <typename T, int N>
516inline Jet<T, N> floor(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800517 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800524template <typename T, int N>
525inline Jet<T, N> ceil(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800526 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))
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800532template <typename T, int N>
533inline Jet<T, N> cbrt(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800534 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)
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800539template <typename T, int N>
540inline Jet<T, N> exp2(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800541 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))
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800547template <typename T, int N>
548inline Jet<T, N> log2(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800549 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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800557template <typename T, int N>
558inline Jet<T, N> hypot(const Jet<T, N>& x, const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800559 // 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800568template <typename T, int N>
569inline Jet<T, N> fmax(const Jet<T, N>& x, const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800570 return x < y ? y : x;
571}
572
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800573template <typename T, int N>
574inline Jet<T, N> fmin(const Jet<T, N>& x, const Jet<T, N>& y) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800575 return y < x ? y : x;
576}
577
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800578// erf is defined as an integral that cannot be expressed analyticaly
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
Austin Schuh70cc9552019-01-21 19:46:48 -0800593// 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(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(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(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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800629template <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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800632}
633
634// See formula http://dlmf.nist.gov/10.6#E1
635// j1(a + h) ~= j1(a) + 0.5 ( j0(a) - j2(a) ) h
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800636template <typename T, int N>
637inline Jet<T, N> BesselJ1(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800638 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800644template <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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800649}
650
651// Jet Classification. It is not clear what the appropriate semantics are for
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800652// 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
Austin Schuh70cc9552019-01-21 19:46:48 -0800655// 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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800662template <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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800667 for (int i = 0; i < N; ++i) {
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800668 result = result & isfinite(f.v[i]);
Austin Schuh70cc9552019-01-21 19:46:48 -0800669 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800670 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800671}
672
673// The jet is infinite if any part of the Jet is infinite.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800674template <typename T, int N>
675inline bool isinf(const Jet<T, N>& f) {
676 auto result = isinf(f.a);
Austin Schuh70cc9552019-01-21 19:46:48 -0800677 for (int i = 0; i < N; ++i) {
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800678 result = result | isinf(f.v[i]);
Austin Schuh70cc9552019-01-21 19:46:48 -0800679 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800680 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800681}
682
Austin Schuh70cc9552019-01-21 19:46:48 -0800683// The jet is NaN if any part of the jet is NaN.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800684template <typename T, int N>
685inline bool isnan(const Jet<T, N>& f) {
686 auto result = isnan(f.a);
Austin Schuh70cc9552019-01-21 19:46:48 -0800687 for (int i = 0; i < N; ++i) {
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800688 result = result | isnan(f.v[i]);
Austin Schuh70cc9552019-01-21 19:46:48 -0800689 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800690 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800691}
692
693// The jet is normal if all parts of the jet are normal.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800694template <typename T, int N>
695inline bool isnormal(const Jet<T, N>& f) {
696 auto result = isnormal(f.a);
Austin Schuh70cc9552019-01-21 19:46:48 -0800697 for (int i = 0; i < N; ++i) {
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800698 result = result & isnormal(f.v[i]);
Austin Schuh70cc9552019-01-21 19:46:48 -0800699 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800700 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800701}
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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800720template <typename T, int N>
721inline bool IsInfinite(const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800722 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.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800729template <typename T, int N>
730inline Jet<T, N> atan2(const Jet<T, N>& g, const Jet<T, N>& f) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800731 // 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);
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800737 return Jet<T, N>(atan2(g.a, f.a), tmp * (-g.a * f.v + f.a * g.v));
Austin Schuh70cc9552019-01-21 19:46:48 -0800738}
739
Austin Schuh70cc9552019-01-21 19:46:48 -0800740// pow -- base is a differentiable function, exponent is a constant.
741// (a+da)^p ~= a^p + p*a^(p-1) da
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800742template <typename T, int N>
743inline Jet<T, N> pow(const Jet<T, N>& f, double g) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800744 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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800759template <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)) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800764 // Handle case 2.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800765 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 }
Austin Schuh70cc9552019-01-21 19:46:48 -0800774 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800775 } else {
776 // Handle case 1.
777 T const tmp = pow(f, g.a);
778 result = Jet<T, N>(tmp, log(f) * tmp * g.v);
Austin Schuh70cc9552019-01-21 19:46:48 -0800779 }
Austin Schuh70cc9552019-01-21 19:46:48 -0800780 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800781
782 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800783}
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
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800821template <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)) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800826 // Handle cases 2 and 3.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800827 if (g.a > T(1)) {
828 result = Jet<T, N>(T(0.0));
829 } else {
830 result = f;
Austin Schuh70cc9552019-01-21 19:46:48 -0800831 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800832
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 }
Austin Schuh70cc9552019-01-21 19:46:48 -0800843 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800844 } 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);
Austin Schuh70cc9552019-01-21 19:46:48 -0800852 }
Austin Schuh70cc9552019-01-21 19:46:48 -0800853 }
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800854
855 return result;
Austin Schuh70cc9552019-01-21 19:46:48 -0800856}
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>
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800862inline std::ostream& operator<<(std::ostream& s, const Jet<T, N>& z) {
Austin Schuh70cc9552019-01-21 19:46:48 -0800863 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}
Austin Schuh70cc9552019-01-21 19:46:48 -0800873} // namespace ceres
874
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800875namespace std {
876template <typename T, int N>
877struct numeric_limits<ceres::Jet<T, N>> {
878 static constexpr bool is_specialized = true;
879 static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
880 static constexpr bool is_integer = std::numeric_limits<T>::is_integer;
881 static constexpr bool is_exact = std::numeric_limits<T>::is_exact;
882 static constexpr bool has_infinity = std::numeric_limits<T>::has_infinity;
883 static constexpr bool has_quiet_NaN = std::numeric_limits<T>::has_quiet_NaN;
884 static constexpr bool has_signaling_NaN =
885 std::numeric_limits<T>::has_signaling_NaN;
886 static constexpr bool is_iec559 = std::numeric_limits<T>::is_iec559;
887 static constexpr bool is_bounded = std::numeric_limits<T>::is_bounded;
888 static constexpr bool is_modulo = std::numeric_limits<T>::is_modulo;
889
890 static constexpr std::float_denorm_style has_denorm =
891 std::numeric_limits<T>::has_denorm;
892 static constexpr std::float_round_style round_style =
893 std::numeric_limits<T>::round_style;
894
895 static constexpr int digits = std::numeric_limits<T>::digits;
896 static constexpr int digits10 = std::numeric_limits<T>::digits10;
897 static constexpr int max_digits10 = std::numeric_limits<T>::max_digits10;
898 static constexpr int radix = std::numeric_limits<T>::radix;
899 static constexpr int min_exponent = std::numeric_limits<T>::min_exponent;
900 static constexpr int min_exponent10 = std::numeric_limits<T>::max_exponent10;
901 static constexpr int max_exponent = std::numeric_limits<T>::max_exponent;
902 static constexpr int max_exponent10 = std::numeric_limits<T>::max_exponent10;
903 static constexpr bool traps = std::numeric_limits<T>::traps;
904 static constexpr bool tinyness_before =
905 std::numeric_limits<T>::tinyness_before;
906
907 static constexpr ceres::Jet<T, N> min() noexcept {
908 return ceres::Jet<T, N>(std::numeric_limits<T>::min());
909 }
910 static constexpr ceres::Jet<T, N> lowest() noexcept {
911 return ceres::Jet<T, N>(std::numeric_limits<T>::lowest());
912 }
913 static constexpr ceres::Jet<T, N> epsilon() noexcept {
914 return ceres::Jet<T, N>(std::numeric_limits<T>::epsilon());
915 }
916 static constexpr ceres::Jet<T, N> round_error() noexcept {
917 return ceres::Jet<T, N>(std::numeric_limits<T>::round_error());
918 }
919 static constexpr ceres::Jet<T, N> infinity() noexcept {
920 return ceres::Jet<T, N>(std::numeric_limits<T>::infinity());
921 }
922 static constexpr ceres::Jet<T, N> quiet_NaN() noexcept {
923 return ceres::Jet<T, N>(std::numeric_limits<T>::quiet_NaN());
924 }
925 static constexpr ceres::Jet<T, N> signaling_NaN() noexcept {
926 return ceres::Jet<T, N>(std::numeric_limits<T>::signaling_NaN());
927 }
928 static constexpr ceres::Jet<T, N> denorm_min() noexcept {
929 return ceres::Jet<T, N>(std::numeric_limits<T>::denorm_min());
930 }
931
932 static constexpr ceres::Jet<T, N> max() noexcept {
933 return ceres::Jet<T, N>(std::numeric_limits<T>::max());
934 }
935};
936
937} // namespace std
938
Austin Schuh70cc9552019-01-21 19:46:48 -0800939namespace Eigen {
940
941// Creating a specialization of NumTraits enables placing Jet objects inside
942// Eigen arrays, getting all the goodness of Eigen combined with autodiff.
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800943template <typename T, int N>
Austin Schuh70cc9552019-01-21 19:46:48 -0800944struct NumTraits<ceres::Jet<T, N>> {
945 typedef ceres::Jet<T, N> Real;
946 typedef ceres::Jet<T, N> NonInteger;
947 typedef ceres::Jet<T, N> Nested;
948 typedef ceres::Jet<T, N> Literal;
949
950 static typename ceres::Jet<T, N> dummy_precision() {
951 return ceres::Jet<T, N>(1e-12);
952 }
953
954 static inline Real epsilon() {
955 return Real(std::numeric_limits<T>::epsilon());
956 }
957
958 static inline int digits10() { return NumTraits<T>::digits10(); }
959
960 enum {
961 IsComplex = 0,
962 IsInteger = 0,
963 IsSigned,
964 ReadCost = 1,
965 AddCost = 1,
966 // For Jet types, multiplication is more expensive than addition.
967 MulCost = 3,
968 HasFloatingPoint = 1,
969 RequireInitialization = 1
970 };
971
Austin Schuh1d1e6ea2020-12-23 21:56:30 -0800972 template <bool Vectorized>
Austin Schuh70cc9552019-01-21 19:46:48 -0800973 struct Div {
974 enum {
975#if defined(EIGEN_VECTORIZE_AVX)
976 AVX = true,
977#else
978 AVX = false,
979#endif
980
981 // Assuming that for Jets, division is as expensive as
982 // multiplication.
983 Cost = 3
984 };
985 };
986
987 static inline Real highest() { return Real(std::numeric_limits<T>::max()); }
988 static inline Real lowest() { return Real(-std::numeric_limits<T>::max()); }
989};
990
Austin Schuh70cc9552019-01-21 19:46:48 -0800991// Specifying the return type of binary operations between Jets and scalar types
992// allows you to perform matrix/array operations with Eigen matrices and arrays
993// such as addition, subtraction, multiplication, and division where one Eigen
994// matrix/array is of type Jet and the other is a scalar type. This improves
995// performance by using the optimized scalar-to-Jet binary operations but
996// is only available on Eigen versions >= 3.3
997template <typename BinaryOp, typename T, int N>
998struct ScalarBinaryOpTraits<ceres::Jet<T, N>, T, BinaryOp> {
999 typedef ceres::Jet<T, N> ReturnType;
1000};
1001template <typename BinaryOp, typename T, int N>
1002struct ScalarBinaryOpTraits<T, ceres::Jet<T, N>, BinaryOp> {
1003 typedef ceres::Jet<T, N> ReturnType;
1004};
Austin Schuh70cc9552019-01-21 19:46:48 -08001005
1006} // namespace Eigen
1007
1008#endif // CERES_PUBLIC_JET_H_