Mitsuba Renderer  0.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
autodiff.h
Go to the documentation of this file.
1 /**
2  Automatic differentiation data type for C++, depends on the Eigen
3  linear algebra library.
4 
5  Copyright (c) 2012 by Wenzel Jakob. Based on code by Jon Kaldor
6  and Eitan Grinspun.
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 
23 #if !defined(__AUTODIFF_H)
24 #define __AUTODIFF_H
25 #define EIGEN_DONT_PARALLELIZE
26 #define EIGEN_NO_DEBUG
27 
28 #include <Eigen/Core>
29 #include <Eigen/Geometry>
30 #include <cmath>
31 #include <stdexcept>
32 
33 #if defined(__WINDOWS__)
34  #define __tls_decl __declspec(thread)
35 #else
36  #define __tls_decl __thread
37 #endif
38 
39 /**
40  * \brief Base class of all automatic differentiation types
41  *
42  * This class records the number of independent variables with respect
43  * to which derivatives are computed.
44  */
46  // ======================================================================
47  /// @{ \name Configuration
48  // ======================================================================
49 
50  /**
51  * \brief Set the independent variable count used by the automatic
52  * differentiation layer
53  *
54  * This function must be called before doing any computations with
55  * \ref DScalar1 or \ref DScalar2. The value will be recorded in
56  * thread-local storage.
57  */
58  static inline void setVariableCount(size_t value) {
59  m_variableCount = value;
60  }
61 
62  /// Get the variable count used by the automatic differentiation layer
63  static inline size_t getVariableCount() {
64  return m_variableCount;
65  }
66 
67  /// @}
68  // ======================================================================
69 
70  static __tls_decl size_t m_variableCount;
71 };
72 
73 #define DECLARE_DIFFSCALAR_BASE() \
74  __tls_decl size_t DiffScalarBase::m_variableCount = 0
75 
76 /**
77  * \brief Automatic differentiation scalar with first-order derivatives
78  *
79  * This class provides an instrumented "scalar" value, which may be dependent on
80  * a number of independent variables. The implementation keeps tracks of
81  * first -order drivatives with respect to these variables using a set
82  * of overloaded operations and implementations of special functions (sin,
83  * tan, exp, ..).
84  *
85  * This is extremely useful for numerical zero-finding, particularly when
86  * analytic derivatives from programs like Maple or Mathematica suffer from
87  * excessively complicated expressions.
88  *
89  * The class relies on templates, which makes it possible to fix the
90  * number of independent variables at compile-time so that instances can
91  * be allocated on the stack. Otherwise, they will be placed on the heap.
92  *
93  * This is an extended C++ port of Jon Kaldor's implementation, which is
94  * based on a C version by Eitan Grinspun at Caltech)
95  *
96  * \sa DScalar2
97  * \author Wenzel Jakob
98  */
99 template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1> >
100  struct DScalar1 : public DiffScalarBase {
101 public:
102  typedef _Scalar Scalar;
103  typedef _Gradient Gradient;
104  typedef Eigen::Matrix<DScalar1, 2, 1> DVector2;
105  typedef Eigen::Matrix<DScalar1, 3, 1> DVector3;
106 
107  // ======================================================================
108  /// @{ \name Constructors and accessors
109  // ======================================================================
110 
111  /// Create a new constant automatic differentiation scalar
112  explicit DScalar1(Scalar value = (Scalar) 0) : value(value) {
113  size_t variableCount = getVariableCount();
114  grad.resize(Eigen::NoChange_t(), variableCount);
115  grad.setZero();
116  }
117 
118  /// Construct a new scalar with the specified value and one first derivative set to 1
119  DScalar1(size_t index, const Scalar &value)
120  : value(value) {
121  size_t variableCount = getVariableCount();
122  grad.resize(Eigen::NoChange_t(), variableCount);
123  grad.setZero();
124  grad(index) = 1;
125  }
126 
127  /// Construct a scalar associated with the given gradient
129  : value(value), grad(grad) { }
130 
131  /// Copy constructor
132  DScalar1(const DScalar1 &s)
133  : value(s.value), grad(s.grad) { }
134 
135  inline const Scalar &getValue() const { return value; }
136  inline const Gradient &getGradient() const { return grad; }
137 
138  // ======================================================================
139  /// @{ \name Addition
140  // ======================================================================
141  friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs) {
142  return DScalar1(lhs.value+rhs.value, lhs.grad+rhs.grad);
143  }
144 
145  friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs) {
146  return DScalar1(lhs.value+rhs, lhs.grad);
147  }
148 
149  friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs) {
150  return DScalar1(rhs.value+lhs, rhs.grad);
151  }
152 
153  inline DScalar1& operator+=(const DScalar1 &s) {
154  value += s.value;
155  grad += s.grad;
156  return *this;
157  }
158 
159  inline DScalar1& operator+=(const Scalar &v) {
160  value += v;
161  return *this;
162  }
163 
164  /// @}
165  // ======================================================================
166 
167  // ======================================================================
168  /// @{ \name Subtraction
169  // ======================================================================
170 
171  friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs) {
172  return DScalar1(lhs.value-rhs.value, lhs.grad-rhs.grad);
173  }
174 
175  friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs) {
176  return DScalar1(lhs.value-rhs, lhs.grad);
177  }
178 
179  friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs) {
180  return DScalar1(lhs-rhs.value, -rhs.grad);
181  }
182 
183  friend DScalar1 operator-(const DScalar1 &s) {
184  return DScalar1(-s.value, -s.grad);
185  }
186 
187  inline DScalar1& operator-=(const DScalar1 &s) {
188  value -= s.value;
189  grad -= s.grad;
190  return *this;
191  }
192 
193  inline DScalar1& operator-=(const Scalar &v) {
194  value -= v;
195  return *this;
196  }
197  /// @}
198  // ======================================================================
199 
200  // ======================================================================
201  /// @{ \name Division
202  // ======================================================================
203  friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs) {
204  if (rhs == 0)
205  throw std::runtime_error("DScalar1: Division by zero!");
206  Scalar inv = 1.0f / rhs;
207  return DScalar1(lhs.value*inv, lhs.grad*inv);
208  }
209 
210  friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs) {
211  return lhs * inverse(rhs);
212  }
213 
214  friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs) {
215  return lhs * inverse(rhs);
216  }
217 
218  friend DScalar1 inverse(const DScalar1 &s) {
219  Scalar valueSqr = s.value*s.value,
220  invValueSqr = (Scalar) 1 / valueSqr;
221 
222  // vn = 1/v, Dvn = -1/(v^2) Dv
223  return DScalar1((Scalar) 1 / s.value, s.grad * -invValueSqr);
224  }
225 
226  inline DScalar1& operator/=(const Scalar &v) {
227  value /= v;
228  grad /= v;
229  return *this;
230  }
231 
232  /// @}
233  // ======================================================================
234 
235  // ======================================================================
236  /// @{ \name Multiplication
237  // ======================================================================
238  inline friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs) {
239  return DScalar1(lhs.value*rhs, lhs.grad*rhs);
240  }
241 
242  inline friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs) {
243  return DScalar1(rhs.value*lhs, rhs.grad*lhs);
244  }
245 
246  inline friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs) {
247  // Product rule
248  return DScalar1(lhs.value*rhs.value,
249  rhs.grad * lhs.value + lhs.grad * rhs.value);
250  }
251 
252  inline DScalar1& operator*=(const Scalar &v) {
253  value *= v;
254  grad *= v;
255  return *this;
256  }
257 
258  /// @}
259  // ======================================================================
260 
261  // ======================================================================
262  /// @{ \name Miscellaneous functions
263  // ======================================================================
264 
265  friend DScalar1 sqrt(const DScalar1 &s) {
266  Scalar sqrtVal = std::sqrt(s.value),
267  temp = (Scalar) 1 / ((Scalar) 2 * sqrtVal);
268 
269  // vn = sqrt(v)
270  // Dvn = 1/(2 sqrt(v)) Dv
271  return DScalar1(sqrtVal, s.grad * temp);
272  }
273 
274  friend DScalar1 pow(const DScalar1 &s, const Scalar &a) {
275  Scalar powVal = std::pow(s.value, a),
276  temp = a * std::pow(s.value, a-1);
277  // vn = v ^ a, Dvn = a*v^(a-1) * Dv
278  return DScalar1(powVal, s.grad * temp);
279  }
280 
281  friend DScalar1 exp(const DScalar1 &s) {
282  Scalar expVal = std::exp(s.value);
283 
284  // vn = exp(v), Dvn = exp(v) * Dv
285  return DScalar1(expVal, s.grad * expVal);
286  }
287 
288  friend DScalar1 log(const DScalar1 &s) {
289  Scalar logVal = std::log(s.value);
290 
291  // vn = log(v), Dvn = Dv / v
292  return DScalar1(logVal, s.grad / s.value);
293  }
294 
295  friend DScalar1 sin(const DScalar1 &s) {
296  // vn = sin(v), Dvn = cos(v) * Dv
297  return DScalar1(std::sin(s.value), s.grad * std::cos(s.value));
298  }
299 
300  friend DScalar1 cos(const DScalar1 &s) {
301  // vn = cos(v), Dvn = -sin(v) * Dv
302  return DScalar1(std::cos(s.value), s.grad * -std::sin(s.value));
303  }
304 
305  friend DScalar1 acos(const DScalar1 &s) {
306  if (std::abs(s.value) >= 1)
307  throw std::runtime_error("acos: Expected a value in (-1, 1)");
308 
309  Scalar temp = -std::sqrt((Scalar) 1 - s.value*s.value);
310 
311  // vn = acos(v), Dvn = -1/sqrt(1-v^2) * Dv
312  return DScalar1(std::acos(s.value),
313  s.grad * ((Scalar) 1 / temp));
314  }
315 
316  friend DScalar1 asin(const DScalar1 &s) {
317  if (std::abs(s.value) >= 1)
318  throw std::runtime_error("asin: Expected a value in (-1, 1)");
319 
320  Scalar temp = std::sqrt((Scalar) 1 - s.value*s.value);
321 
322  // vn = asin(v), Dvn = 1/sqrt(1-v^2) * Dv
323  return DScalar1(std::asin(s.value),
324  s.grad * ((Scalar) 1 / temp));
325  }
326 
327  friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x) {
328  Scalar denom = x.value*x.value + y.value*y.value;
329 
330  // vn = atan2(y, x), Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
331  return DScalar1(std::atan2(y.value, x.value),
332  y.grad * (x.value / denom) - x.grad * (y.value / denom));
333  }
334 
335  /// @}
336  // ======================================================================
337 
338  // ======================================================================
339  /// @{ \name Comparison and assignment
340  // ======================================================================
341 
342  inline void operator=(const DScalar1& s) { value = s.value; grad = s.grad; }
343  inline void operator=(const Scalar &v) { value = v; grad.setZero(); }
344  inline bool operator<(const DScalar1& s) const { return value < s.value; }
345  inline bool operator<=(const DScalar1& s) const { return value <= s.value; }
346  inline bool operator>(const DScalar1& s) const { return value > s.value; }
347  inline bool operator>=(const DScalar1& s) const { return value >= s.value; }
348  inline bool operator<(const Scalar& s) const { return value < s; }
349  inline bool operator<=(const Scalar& s) const { return value <= s; }
350  inline bool operator>(const Scalar& s) const { return value > s; }
351  inline bool operator>=(const Scalar& s) const { return value >= s; }
352  inline bool operator==(const Scalar& s) const { return value == s; }
353  inline bool operator!=(const Scalar& s) const { return value != s; }
354 
355  /// @}
356  // ======================================================================
357 
358  // ======================================================================
359  /// @{ \name Comparison and assignment
360  // ======================================================================
361 
362  #if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
363  /// Initialize a constant two-dimensional vector
364  static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v) {
365  return DVector2(DScalar1(v.x), DScalar1(v.y));
366  }
367 
368  /// Initialize a constant two-dimensional vector
369  static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p) {
370  return DVector2(DScalar1(p.x), DScalar1(p.y));
371  }
372 
373  /// Create a constant three-dimensional vector
374  static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v) {
375  return DVector3(DScalar1(v.x), DScalar1(v.y), DScalar1(v.z));
376  }
377 
378  /// Create a constant three-dimensional vector
379  static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p) {
380  return DVector3(DScalar1(p.x), DScalar1(p.y), DScalar1(p.z));
381  }
382  #endif
383 
384  /// @}
385  // ======================================================================
386 protected:
389 };
390 
391 template <typename Scalar, typename VecType>
392  std::ostream &operator<<(std::ostream &out, const DScalar1<Scalar, VecType> &s) {
393  out << "[" << s.getValue()
394  << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
395  << "]";
396  return out;
397 }
398 
399 /**
400  * \brief Automatic differentiation scalar with first- and second-order derivatives
401  *
402  * This class provides an instrumented "scalar" value, which may be dependent on
403  * a number of independent variables. The implementation keeps tracks of first
404  * and second-order drivatives with respect to these variables using a set
405  * of overloaded operations and implementations of special functions (sin,
406  * tan, exp, ..).
407  *
408  * This is extremely useful for numerical optimization, particularly when
409  * analytic derivatives from programs like Maple or Mathematica suffer from
410  * excessively complicated expressions.
411  *
412  * The class relies on templates, which makes it possible to fix the
413  * number of independent variables at compile-time so that instances can
414  * be allocated on the stack. Otherwise, they will be placed on the heap.
415  *
416  * This is an extended C++ port of Jon Kaldor's implementation, which is
417  * based on a C version by Eitan Grinspun at Caltech)
418  *
419  * \sa DScalar1
420  * \author Wenzel Jakob
421  */
422 template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>,
423  typename _Hessian = Eigen::Matrix<_Scalar, Eigen::Dynamic, Eigen::Dynamic> >
424  struct DScalar2 : public DiffScalarBase {
425 public:
426  typedef _Scalar Scalar;
427  typedef _Gradient Gradient;
428  typedef _Hessian Hessian;
429  typedef Eigen::Matrix<DScalar2, 2, 1> DVector2;
430  typedef Eigen::Matrix<DScalar2, 3, 1> DVector3;
431 
432  // ======================================================================
433  /// @{ \name Constructors and accessors
434  // ======================================================================
435 
436  /// Create a new constant automatic differentiation scalar
437  explicit DScalar2(Scalar value = (Scalar) 0) : value(value) {
438  size_t variableCount = getVariableCount();
439 
440  grad.resize(Eigen::NoChange_t(), variableCount);
441  grad.setZero();
442  hess.resize(variableCount, variableCount);
443  hess.setZero();
444  }
445 
446  /// Construct a new scalar with the specified value and one first derivative set to 1
447  DScalar2(size_t index, const Scalar &value)
448  : value(value) {
449  size_t variableCount = getVariableCount();
450 
451  grad.resize(Eigen::NoChange_t(), variableCount);
452  grad.setZero();
453  grad(index) = 1;
454  hess.resize(variableCount, variableCount);
455  hess.setZero();
456  }
457 
458  /// Construct a scalar associated with the given gradient and Hessian
460  : value(value), grad(grad), hess(hess) { }
461 
462  /// Copy constructor
463  DScalar2(const DScalar2 &s)
464  : value(s.value), grad(s.grad), hess(s.hess) { }
465 
466  inline const Scalar &getValue() const { return value; }
467  inline const Gradient &getGradient() const { return grad; }
468  inline const Hessian &getHessian() const { return hess; }
469 
470  // ======================================================================
471  /// @{ \name Addition
472  // ======================================================================
473  friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs) {
474  return DScalar2(lhs.value+rhs.value,
475  lhs.grad+rhs.grad, lhs.hess+rhs.hess);
476  }
477 
478  friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs) {
479  return DScalar2(lhs.value+rhs, lhs.grad, lhs.hess);
480  }
481 
482  friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs) {
483  return DScalar2(rhs.value+lhs, rhs.grad, rhs.hess);
484  }
485 
486  inline DScalar2& operator+=(const DScalar2 &s) {
487  value += s.value;
488  grad += s.grad;
489  hess += s.hess;
490  return *this;
491  }
492 
493  inline DScalar2& operator+=(const Scalar &v) {
494  value += v;
495  return *this;
496  }
497 
498  /// @}
499  // ======================================================================
500 
501  // ======================================================================
502  /// @{ \name Subtraction
503  // ======================================================================
504 
505  friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs) {
506  return DScalar2(lhs.value-rhs.value, lhs.grad-rhs.grad, lhs.hess-rhs.hess);
507  }
508 
509  friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs) {
510  return DScalar2(lhs.value-rhs, lhs.grad, lhs.hess);
511  }
512 
513  friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs) {
514  return DScalar2(lhs-rhs.value, -rhs.grad, -rhs.hess);
515  }
516 
517  friend DScalar2 operator-(const DScalar2 &s) {
518  return DScalar2(-s.value, -s.grad, -s.hess);
519  }
520 
521  inline DScalar2& operator-=(const DScalar2 &s) {
522  value -= s.value;
523  grad -= s.grad;
524  hess -= s.hess;
525  return *this;
526  }
527 
528  inline DScalar2& operator-=(const Scalar &v) {
529  value -= v;
530  return *this;
531  }
532  /// @}
533  // ======================================================================
534 
535  // ======================================================================
536  /// @{ \name Division
537  // ======================================================================
538  friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs) {
539  if (rhs == 0)
540  throw std::runtime_error("DScalar2: Division by zero!");
541  Scalar inv = 1.0f / rhs;
542  return DScalar2(lhs.value*inv, lhs.grad*inv, lhs.hess*inv);
543  }
544 
545  friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs) {
546  return lhs * inverse(rhs);
547  }
548 
549  friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs) {
550  return lhs * inverse(rhs);
551  }
552 
553  friend DScalar2 inverse(const DScalar2 &s) {
554  Scalar valueSqr = s.value*s.value,
555  valueCub = valueSqr * s.value,
556  invValueSqr = (Scalar) 1 / valueSqr;
557 
558  // vn = 1/v
559  DScalar2 result((Scalar) 1 / s.value);
560 
561  // Dvn = -1/(v^2) Dv
562  result.grad = s.grad * -invValueSqr;
563 
564  // D^2vn = -1/(v^2) D^2v + 2/(v^3) Dv Dv^T
565  result.hess = s.hess * -invValueSqr;
566  result.hess += s.grad * s.grad.transpose()
567  * ((Scalar) 2 / valueCub);
568 
569  return result;
570  }
571 
572  inline DScalar2& operator/=(const Scalar &v) {
573  value /= v;
574  grad /= v;
575  hess /= v;
576  return *this;
577  }
578  /// @}
579  // ======================================================================
580 
581  // ======================================================================
582  /// @{ \name Multiplication
583  // ======================================================================
584  friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs) {
585  return DScalar2(lhs.value*rhs, lhs.grad*rhs, lhs.hess*rhs);
586  }
587 
588  friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs) {
589  return DScalar2(rhs.value*lhs, rhs.grad*lhs, rhs.hess*lhs);
590  }
591 
592  friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs) {
593  DScalar2 result(lhs.value*rhs.value);
594 
595  /// Product rule
596  result.grad = rhs.grad * lhs.value + lhs.grad * rhs.value;
597 
598  // (i,j) = g*F_xixj + g*G_xixj + F_xi*G_xj + F_xj*G_xi
599  result.hess = rhs.hess * lhs.value;
600  result.hess += lhs.hess * rhs.value;
601  result.hess += lhs.grad * rhs.grad.transpose();
602  result.hess += rhs.grad * lhs.grad.transpose();
603 
604  return result;
605  }
606 
607  inline DScalar2& operator*=(const Scalar &v) {
608  value *= v;
609  grad *= v;
610  hess *= v;
611  return *this;
612  }
613 
614  /// @}
615  // ======================================================================
616 
617  // ======================================================================
618  /// @{ \name Miscellaneous functions
619  // ======================================================================
620 
621  friend DScalar2 sqrt(const DScalar2 &s) {
622  Scalar sqrtVal = std::sqrt(s.value),
623  temp = (Scalar) 1 / ((Scalar) 2 * sqrtVal);
624 
625  // vn = sqrt(v)
626  DScalar2 result(sqrtVal);
627 
628  // Dvn = 1/(2 sqrt(v)) Dv
629  result.grad = s.grad * temp;
630 
631  // D^2vn = 1/(2 sqrt(v)) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
632  result.hess = s.hess * temp;
633  result.hess += s.grad * s.grad.transpose()
634  * (-(Scalar) 1 / ((Scalar) 4 * s.value * sqrtVal));
635 
636  return result;
637  }
638 
639  friend DScalar2 pow(const DScalar2 &s, const Scalar &a) {
640  Scalar powVal = std::pow(s.value, a),
641  temp = a * std::pow(s.value, a-1);
642  // vn = v ^ a
643  DScalar2 result(powVal);
644 
645  // Dvn = a*v^(a-1) * Dv
646  result.grad = s.grad * temp;
647 
648  // D^2vn = a*v^(a-1) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
649  result.hess = s.hess * temp;
650  result.hess += s.grad * s.grad.transpose()
651  * (a * (a-1) * std::pow(s.value, a-2));
652 
653  return result;
654  }
655 
656  friend DScalar2 exp(const DScalar2 &s) {
657  Scalar expVal = std::exp(s.value);
658 
659  // vn = exp(v)
660  DScalar2 result(expVal);
661 
662  // Dvn = exp(v) * Dv
663  result.grad = s.grad * expVal;
664 
665  // D^2vn = exp(v) * Dv*Dv^T + exp(v) * D^2v
666  result.hess = (s.grad * s.grad.transpose()
667  + s.hess) * expVal;
668 
669  return result;
670  }
671 
672  friend DScalar2 log(const DScalar2 &s) {
673  Scalar logVal = std::log(s.value);
674 
675  // vn = log(v)
676  DScalar2 result(logVal);
677 
678  // Dvn = Dv / v
679  result.grad = s.grad / s.value;
680 
681  // D^2vn = (v*D^2v - Dv*Dv^T)/(v^2)
682  result.hess = s.hess / s.value -
683  (s.grad * s.grad.transpose() / (s.value*s.value));
684 
685  return result;
686  }
687 
688  friend DScalar2 sin(const DScalar2 &s) {
689  Scalar sinVal = std::sin(s.value),
690  cosVal = std::cos(s.value);
691 
692  // vn = sin(v)
693  DScalar2 result(sinVal);
694 
695  // Dvn = cos(v) * Dv
696  result.grad = s.grad * cosVal;
697 
698  // D^2vn = -sin(v) * Dv*Dv^T + cos(v) * Dv^2
699  result.hess = s.hess * cosVal;
700  result.hess += s.grad * s.grad.transpose() * -sinVal;
701 
702  return result;
703  }
704 
705  friend DScalar2 cos(const DScalar2 &s) {
706  Scalar sinVal = std::sin(s.value),
707  cosVal = std::cos(s.value);
708  // vn = cos(v)
709  DScalar2 result(cosVal);
710 
711  // Dvn = -sin(v) * Dv
712  result.grad = s.grad * -sinVal;
713 
714  // D^2vn = -cos(v) * Dv*Dv^T - sin(v) * Dv^2
715  result.hess = s.hess * -sinVal;
716  result.hess += s.grad * s.grad.transpose() * -cosVal;
717 
718  return result;
719  }
720 
721  friend DScalar2 acos(const DScalar2 &s) {
722  if (std::abs(s.value) >= 1)
723  throw std::runtime_error("acos: Expected a value in (-1, 1)");
724 
725  Scalar temp = -std::sqrt((Scalar) 1 - s.value*s.value);
726 
727  // vn = acos(v)
728  DScalar2 result(std::acos(s.value));
729 
730  // Dvn = -1/sqrt(1-v^2) * Dv
731  result.grad = s.grad * ((Scalar) 1 / temp);
732 
733  // D^2vn = -1/sqrt(1-v^2) * D^2v - v/[(1-v^2)^(3/2)] * Dv*Dv^T
734  result.hess = s.hess * ((Scalar) 1 / temp);
735  result.hess += s.grad * s.grad.transpose()
736  * s.value / (temp*temp*temp);
737 
738  return result;
739  }
740 
741  friend DScalar2 asin(const DScalar2 &s) {
742  if (std::abs(s.value) >= 1)
743  throw std::runtime_error("asin: Expected a value in (-1, 1)");
744 
745  Scalar temp = std::sqrt((Scalar) 1 - s.value*s.value);
746 
747  // vn = asin(v)
748  DScalar2 result(std::asin(s.value));
749 
750  // Dvn = 1/sqrt(1-v^2) * Dv
751  result.grad = s.grad * ((Scalar) 1 / temp);
752 
753  // D^2vn = 1/sqrt(1-v*v) * D^2v + v/[(1-v^2)^(3/2)] * Dv*Dv^T
754  result.hess = s.hess * ((Scalar) 1 / temp);
755  result.hess += s.grad * s.grad.transpose()
756  * s.value / (temp*temp*temp);
757 
758  return result;
759  }
760 
761  friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x) {
762  // vn = atan2(y, x)
763  DScalar2 result(std::atan2(y.value, x.value));
764 
765  // Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
766  Scalar denom = x.value*x.value + y.value*y.value,
767  denomSqr = denom*denom;
768  result.grad = y.grad * (x.value / denom)
769  - x.grad * (y.value / denom);
770 
771  // D^2vn = (Dy*Dx^T + xD^2y - Dx*Dy^T - yD^2x) / (x^2+y^2)
772  // - [(x*Dy - y*Dx) * (2*x*Dx + 2*y*Dy)^T] / (x^2+y^2)^2
773  result.hess = (y.hess*x.value
774  + y.grad * x.grad.transpose()
775  - x.hess*y.value
776  - x.grad*y.grad.transpose()
777  ) / denom;
778 
779  result.hess -=
780  (y.grad*(x.value/denomSqr) - x.grad*(y.value/denomSqr)) *
781  (x.grad*((Scalar) 2 * x.value) + y.grad*((Scalar) 2 * y.value)).transpose();
782 
783  return result;
784  }
785 
786  /// @}
787  // ======================================================================
788 
789  // ======================================================================
790  /// @{ \name Comparison and assignment
791  // ======================================================================
792 
793  inline void operator=(const DScalar2& s) { value = s.value; grad = s.grad; hess = s.hess; }
794  inline void operator=(const Scalar &v) { value = v; grad.setZero(); hess.setZero(); }
795  inline bool operator<(const DScalar2& s) const { return value < s.value; }
796  inline bool operator<=(const DScalar2& s) const { return value <= s.value; }
797  inline bool operator>(const DScalar2& s) const { return value > s.value; }
798  inline bool operator>=(const DScalar2& s) const { return value >= s.value; }
799  inline bool operator<(const Scalar& s) const { return value < s; }
800  inline bool operator<=(const Scalar& s) const { return value <= s; }
801  inline bool operator>(const Scalar& s) const { return value > s; }
802  inline bool operator>=(const Scalar& s) const { return value >= s; }
803  inline bool operator==(const Scalar& s) const { return value == s; }
804  inline bool operator!=(const Scalar& s) const { return value != s; }
805 
806  /// @}
807  // ======================================================================
808 
809  // ======================================================================
810  /// @{ \name Comparison and assignment
811  // ======================================================================
812 
813  #if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
814  /// Initialize a constant two-dimensional vector
815  static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v) {
816  return DVector2(DScalar2(v.x), DScalar2(v.y));
817  }
818 
819  /// Initialize a constant two-dimensional vector
820  static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p) {
821  return DVector2(DScalar2(p.x), DScalar2(p.y));
822  }
823 
824  /// Create a constant three-dimensional vector
825  static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v) {
826  return DVector3(DScalar2(v.x), DScalar2(v.y), DScalar2(v.z));
827  }
828 
829  /// Create a constant three-dimensional vector
830  static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p) {
831  return DVector3(DScalar2(p.x), DScalar2(p.y), DScalar2(p.z));
832  }
833  #endif
834 
835  /// @}
836  // ======================================================================
837 protected:
841 };
842 
843 template <typename Scalar, typename VecType, typename MatType>
844  std::ostream &operator<<(std::ostream &out, const DScalar2<Scalar, VecType, MatType> &s) {
845  out << "[" << s.getValue()
846  << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
847  << ", hess=" << s.getHessian().format(Eigen::IOFormat(4, 0, ", ", "; ", "", "", "[", "]"))
848  << "]";
849  return out;
850 }
851 
852 #endif /* __AUTODIFF_H */
friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:214
friend DScalar2 asin(const DScalar2 &s)
Definition: autodiff.h:741
DScalar2 & operator+=(const Scalar &v)
Definition: autodiff.h:493
bool operator>=(const Scalar &s) const
Definition: autodiff.h:351
friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:171
Base class of all automatic differentiation types.
Definition: autodiff.h:45
bool operator<=(const Scalar &s) const
Definition: autodiff.h:349
friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:179
bool operator>=(const Scalar &s) const
Definition: autodiff.h:802
friend DScalar2 log(const DScalar2 &s)
Definition: autodiff.h:672
Eigen::Matrix< DScalar1, 2, 1 > DVector2
Definition: autodiff.h:104
T y
Definition: point.h:419
DScalar2 & operator-=(const DScalar2 &s)
Definition: autodiff.h:521
friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x)
Definition: autodiff.h:761
DScalar2 & operator*=(const Scalar &v)
Definition: autodiff.h:607
T x
Definition: point.h:419
Eigen::Matrix< DScalar2, 3, 1 > DVector3
Definition: autodiff.h:430
Automatic differentiation scalar with first- and second-order derivatives.
Definition: autodiff.h:424
friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:478
static size_t getVariableCount()
Get the variable count used by the automatic differentiation layer.
Definition: autodiff.h:63
friend DScalar2 sin(const DScalar2 &s)
Definition: autodiff.h:688
void operator=(const DScalar2 &s)
Definition: autodiff.h:793
T y
Definition: vector.h:455
DScalar1 & operator*=(const Scalar &v)
Definition: autodiff.h:252
friend DScalar2 operator-(const DScalar2 &s)
Definition: autodiff.h:517
friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:238
bool operator<=(const DScalar1 &s) const
Definition: autodiff.h:345
friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:509
friend DScalar1 log(const DScalar1 &s)
Definition: autodiff.h:288
friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:513
friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:584
Eigen::Matrix< DScalar2, 2, 1 > DVector2
Definition: autodiff.h:429
Eigen::Matrix< DScalar1, 3, 1 > DVector3
Definition: autodiff.h:105
friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:549
friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:246
_Gradient Gradient
Definition: autodiff.h:427
friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
Definition: autodiff.h:327
friend DScalar1 sin(const DScalar1 &s)
Definition: autodiff.h:295
friend DScalar1 sqrt(const DScalar1 &s)
Definition: autodiff.h:265
DScalar2 & operator+=(const DScalar2 &s)
Definition: autodiff.h:486
_Hessian Hessian
Definition: autodiff.h:428
friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:538
const Scalar & getValue() const
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:135
friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:473
bool operator>(const Scalar &s) const
Definition: autodiff.h:801
bool operator<=(const DScalar2 &s) const
Definition: autodiff.h:796
bool operator==(const Scalar &s) const
Definition: autodiff.h:803
Automatic differentiation scalar with first-order derivatives.
Definition: autodiff.h:100
static __thread size_t m_variableCount
Definition: autodiff.h:70
friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:505
DScalar1 & operator-=(const DScalar1 &s)
Definition: autodiff.h:187
friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:482
friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:592
friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:141
friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:149
friend DScalar1 exp(const DScalar1 &s)
Definition: autodiff.h:281
DScalar1(Scalar value, const Gradient &grad)
Construct a scalar associated with the given gradient.
Definition: autodiff.h:128
T x
Definition: vector.h:251
T x
Definition: point.h:226
const Hessian & getHessian() const
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:468
DScalar1(size_t index, const Scalar &value)
Construct a new scalar with the specified value and one first derivative set to 1.
Definition: autodiff.h:119
friend DScalar2 cos(const DScalar2 &s)
Definition: autodiff.h:705
friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:210
friend DScalar1 inverse(const DScalar1 &s)
Definition: autodiff.h:218
Parameterizable two-dimensional point data structure.
Definition: point.h:222
DScalar1 & operator+=(const Scalar &v)
Definition: autodiff.h:159
bool operator<(const Scalar &s) const
Definition: autodiff.h:348
bool operator>(const DScalar2 &s) const
Definition: autodiff.h:797
bool operator<(const DScalar1 &s) const
Definition: autodiff.h:344
_Gradient Gradient
Definition: autodiff.h:103
friend DScalar2 pow(const DScalar2 &s, const Scalar &a)
Definition: autodiff.h:639
void operator=(const Scalar &v)
Definition: autodiff.h:343
friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:588
DScalar2(size_t index, const Scalar &value)
Construct a new scalar with the specified value and one first derivative set to 1.
Definition: autodiff.h:447
T z
Definition: vector.h:455
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Definition: autodiff.h:58
DScalar1(Scalar value=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:112
Parameterizable three-dimensional vector data structure.
Definition: vector.h:450
friend DScalar1 asin(const DScalar1 &s)
Definition: autodiff.h:316
friend DScalar2 acos(const DScalar2 &s)
Definition: autodiff.h:721
DScalar2 & operator/=(const Scalar &v)
Definition: autodiff.h:572
void operator=(const Scalar &v)
Definition: autodiff.h:794
friend DScalar1 cos(const DScalar1 &s)
Definition: autodiff.h:300
const Gradient & getGradient() const
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:136
DScalar2(Scalar value, const Gradient &grad, const Hessian &hess)
Construct a scalar associated with the given gradient and Hessian.
Definition: autodiff.h:459
T x
Definition: vector.h:455
Gradient grad
Definition: autodiff.h:388
DScalar1 & operator-=(const Scalar &v)
Definition: autodiff.h:193
Hessian hess
Definition: autodiff.h:840
friend DScalar2 exp(const DScalar2 &s)
Definition: autodiff.h:656
friend DScalar1 pow(const DScalar1 &s, const Scalar &a)
Definition: autodiff.h:274
bool operator<(const Scalar &s) const
Definition: autodiff.h:799
friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:145
bool operator<=(const Scalar &s) const
Definition: autodiff.h:800
bool operator!=(const Scalar &s) const
Definition: autodiff.h:804
Parameterizable three-dimensional point data structure.
Definition: point.h:415
T y
Definition: vector.h:251
friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:242
friend DScalar1 operator-(const DScalar1 &s)
Definition: autodiff.h:183
DScalar1 & operator+=(const DScalar1 &s)
Definition: autodiff.h:153
DScalar1 & operator/=(const Scalar &v)
Definition: autodiff.h:226
friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:175
Scalar value
Definition: autodiff.h:387
Parameterizable two-dimensional vector data structure.
Definition: vector.h:246
_Scalar Scalar
Definition: autodiff.h:102
DScalar2 & operator-=(const Scalar &v)
Definition: autodiff.h:528
const Gradient & getGradient() const
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:467
bool operator>=(const DScalar1 &s) const
Definition: autodiff.h:347
Scalar value
Definition: autodiff.h:838
bool operator==(const Scalar &s) const
Definition: autodiff.h:352
_Scalar Scalar
Definition: autodiff.h:426
friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:545
void operator=(const DScalar1 &s)
Definition: autodiff.h:342
DScalar1(const DScalar1 &s)
Copy constructor.
Definition: autodiff.h:132
bool operator!=(const Scalar &s) const
Definition: autodiff.h:353
bool operator>(const DScalar1 &s) const
Definition: autodiff.h:346
bool operator>(const Scalar &s) const
Definition: autodiff.h:350
DScalar2(Scalar value=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:437
bool operator>=(const DScalar2 &s) const
Definition: autodiff.h:798
friend DScalar1 acos(const DScalar1 &s)
Definition: autodiff.h:305
#define __tls_decl
Definition: autodiff.h:36
friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:203
T z
Definition: point.h:419
DScalar2(const DScalar2 &s)
Copy constructor.
Definition: autodiff.h:463
const Scalar & getValue() const
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:466
friend DScalar2 inverse(const DScalar2 &s)
Definition: autodiff.h:553
bool operator<(const DScalar2 &s) const
Definition: autodiff.h:795
Gradient grad
Definition: autodiff.h:839
T y
Definition: point.h:226
friend DScalar2 sqrt(const DScalar2 &s)
Definition: autodiff.h:621