Wildmeshing Toolkit
autodiff.h
Go to the documentation of this file.
1 // clang-format off
2 
25 #ifndef __AUTODIFF_H
26 #define __AUTODIFF_H
27 
28 #ifndef EIGEN_DONT_PARALLELIZE
29 #define EIGEN_DONT_PARALLELIZE
30 #endif
31 
32 #include <Eigen/Core>
33 #include <cmath>
34 #include <stdexcept>
35 #include <limits>
36 
44 {
45  // ======================================================================
47  // ======================================================================
48 
57  static inline void setVariableCount(size_t value)
58  {
59  m_variableCount = value;
60  }
61 
63  static inline size_t getVariableCount()
64  {
65  return m_variableCount;
66  }
67 
69  // ======================================================================
70 
71  // #ifdef WIN32
72  // static __declspec(thread) size_t m_variableCount;
73  // #else
74  // static __thread size_t m_variableCount;
75  // #endif
76  static thread_local size_t m_variableCount;
77 };
78 
79 // #ifdef WIN32
80 // #define DECLARE_DIFFSCALAR_BASE()
81 // __declspec(thread) size_t DiffScalarBase::m_variableCount = 0
82 // #else
83 // #define DECLARE_DIFFSCALAR_BASE()
84 // __thread size_t DiffScalarBase::m_variableCount = 0
85 // #endif
86 
87 #define DECLARE_DIFFSCALAR_BASE() \
88  thread_local size_t DiffScalarBase::m_variableCount = 0
89 
113 template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>>
114 struct DScalar1 : public DiffScalarBase
115 {
116 public:
117  typedef _Scalar Scalar;
118  typedef _Gradient Gradient;
119  typedef Eigen::Matrix<DScalar1, 2, 1> DVector2;
120  typedef Eigen::Matrix<DScalar1, 3, 1> DVector3;
121 
122  // ======================================================================
124  // ======================================================================
125 
127  explicit DScalar1(Scalar value_ = (Scalar)0) : value(value_)
128  {
129  size_t variableCount = getVariableCount();
130  grad.resize(variableCount);
131  grad.setZero();
132  }
133 
135  DScalar1(size_t index, const Scalar &value_)
136  : value(value_)
137  {
138  size_t variableCount = getVariableCount();
139  grad.resize(variableCount);
140  grad.setZero();
141  grad(index) = 1;
142  }
143 
145  DScalar1(Scalar value_, const Gradient &grad_)
146  : value(value_), grad(grad_) {}
147 
149  DScalar1(const DScalar1 &s)
150  : value(s.value), grad(s.grad) {}
151 
152  inline const Scalar &getValue() const { return value; }
153  inline const Gradient &getGradient() const { return grad; }
154 
155  // ======================================================================
157  // ======================================================================
158  friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs)
159  {
160  return DScalar1(lhs.value + rhs.value, lhs.grad + rhs.grad);
161  }
162 
163  friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs)
164  {
165  return DScalar1(lhs.value + rhs, lhs.grad);
166  }
167 
168  friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs)
169  {
170  return DScalar1(rhs.value + lhs, rhs.grad);
171  }
172 
173  inline DScalar1 &operator+=(const DScalar1 &s)
174  {
175  value += s.value;
176  grad += s.grad;
177  return *this;
178  }
179 
180  inline DScalar1 &operator+=(const Scalar &v)
181  {
182  value += v;
183  return *this;
184  }
185 
187  // ======================================================================
188 
189  // ======================================================================
191  // ======================================================================
192 
193  friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs)
194  {
195  return DScalar1(lhs.value - rhs.value, lhs.grad - rhs.grad);
196  }
197 
198  friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
199  {
200  return DScalar1(lhs.value - rhs, lhs.grad);
201  }
202 
203  friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs)
204  {
205  return DScalar1(lhs - rhs.value, -rhs.grad);
206  }
207 
208  friend DScalar1 operator-(const DScalar1 &s)
209  {
210  return DScalar1(-s.value, -s.grad);
211  }
212 
213  inline DScalar1 &operator-=(const DScalar1 &s)
214  {
215  value -= s.value;
216  grad -= s.grad;
217  return *this;
218  }
219 
220  inline DScalar1 &operator-=(const Scalar &v)
221  {
222  value -= v;
223  return *this;
224  }
226  // ======================================================================
227 
228  // ======================================================================
230  // ======================================================================
231  friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs)
232  {
233  if (rhs == 0)
234  throw std::runtime_error("DScalar1: Division by zero!");
235  Scalar inv = 1.0f / rhs;
236  return DScalar1(lhs.value * inv, lhs.grad * inv);
237  }
238 
239  friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs)
240  {
241  return lhs * inverse(rhs);
242  }
243 
244  friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs)
245  {
246  return lhs * inverse(rhs);
247  }
248 
249  friend DScalar1 inverse(const DScalar1 &s)
250  {
251  Scalar valueSqr = s.value * s.value,
252  invValueSqr = (Scalar)1 / valueSqr;
253 
254  // vn = 1/v, Dvn = -1/(v^2) Dv
255  return DScalar1((Scalar)1 / s.value, s.grad * -invValueSqr);
256  }
257 
258  inline DScalar1 &operator/=(const Scalar &v)
259  {
260  value /= v;
261  grad /= v;
262  return *this;
263  }
264 
266  // ======================================================================
267 
268  // ======================================================================
270  // ======================================================================
271  inline friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
272  {
273  return DScalar1(lhs.value * rhs, lhs.grad * rhs);
274  }
275 
276  inline friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs)
277  {
278  return DScalar1(rhs.value * lhs, rhs.grad * lhs);
279  }
280 
281  inline friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs)
282  {
283  // Product rule
284  return DScalar1(lhs.value * rhs.value,
285  rhs.grad * lhs.value + lhs.grad * rhs.value);
286  }
287 
288  inline DScalar1 &operator*=(const Scalar &v)
289  {
290  value *= v;
291  grad *= v;
292  return *this;
293  }
294 
296  // ======================================================================
297 
298  // ======================================================================
300  // ======================================================================
301 
302  friend DScalar1 abs(const DScalar1 &s)
303  {
304  return s.value < 0? -s: s;
305  }
306 
307  friend DScalar1 sqrt(const DScalar1 &s)
308  {
309  Scalar sqrtVal = std::sqrt(s.value),
310  temp = (Scalar)1 / ((Scalar)2 * sqrtVal);
311 
312  // vn = sqrt(v)
313  // Dvn = 1/(2 sqrt(v)) Dv
314  return DScalar1(sqrtVal, s.grad * temp);
315  }
316 
317  friend DScalar1 pow(const DScalar1 &s, const Scalar &a)
318  {
319  Scalar powVal = std::pow(s.value, a),
320  temp = a * std::pow(s.value, a - 1);
321  // vn = v ^ a, Dvn = a*v^(a-1) * Dv
322  return DScalar1(powVal, s.grad * temp);
323  }
324 
325  friend DScalar1 exp(const DScalar1 &s)
326  {
327  Scalar expVal = std::exp(s.value);
328 
329  // vn = exp(v), Dvn = exp(v) * Dv
330  return DScalar1(expVal, s.grad * expVal);
331  }
332 
333  friend DScalar1 log(const DScalar1 &s)
334  {
335  Scalar logVal = std::log(s.value);
336 
337  // vn = log(v), Dvn = Dv / v
338  return DScalar1(logVal, s.grad / s.value);
339  }
340 
341  friend DScalar1 sin(const DScalar1 &s)
342  {
343  // vn = sin(v), Dvn = cos(v) * Dv
344  return DScalar1(std::sin(s.value), s.grad * std::cos(s.value));
345  }
346 
347  friend DScalar1 cos(const DScalar1 &s)
348  {
349  // vn = cos(v), Dvn = -sin(v) * Dv
350  return DScalar1(std::cos(s.value), s.grad * -std::sin(s.value));
351  }
352 
353  friend DScalar1 acos(const DScalar1 &s)
354  {
355  if (std::abs(s.value) >= 1)
356  throw std::runtime_error("acos: Expected a value in (-1, 1)");
357 
358  Scalar temp = -std::sqrt((Scalar)1 - s.value * s.value);
359 
360  // vn = acos(v), Dvn = -1/sqrt(1-v^2) * Dv
361  return DScalar1(std::acos(s.value),
362  s.grad * ((Scalar)1 / temp));
363  }
364 
365  friend DScalar1 asin(const DScalar1 &s)
366  {
367  if (std::abs(s.value) >= 1)
368  throw std::runtime_error("asin: Expected a value in (-1, 1)");
369 
370  Scalar temp = std::sqrt((Scalar)1 - s.value * s.value);
371 
372  // vn = asin(v), Dvn = 1/sqrt(1-v^2) * Dv
373  return DScalar1(std::asin(s.value),
374  s.grad * ((Scalar)1 / temp));
375  }
376 
377  friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
378  {
379  Scalar denom = x.value * x.value + y.value * y.value;
380 
381  // vn = atan2(y, x), Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
382  return DScalar1(std::atan2(y.value, x.value),
383  y.grad * (x.value / denom) - x.grad * (y.value / denom));
384  }
385 
387  // ======================================================================
388 
389  // ======================================================================
391  // ======================================================================
392 
393  inline void operator=(const DScalar1 &s)
394  {
395  value = s.value;
396  grad = s.grad;
397  }
398  inline void operator=(const Scalar &v)
399  {
400  value = v;
401  grad.setZero();
402  }
403  inline bool operator<(const DScalar1 &s) const { return value < s.value; }
404  inline bool operator<=(const DScalar1 &s) const { return value <= s.value; }
405  inline bool operator>(const DScalar1 &s) const { return value > s.value; }
406  inline bool operator>=(const DScalar1 &s) const { return value >= s.value; }
407  inline bool operator<(const Scalar &s) const { return value < s; }
408  inline bool operator<=(const Scalar &s) const { return value <= s; }
409  inline bool operator>(const Scalar &s) const { return value > s; }
410  inline bool operator>=(const Scalar &s) const { return value >= s; }
411  inline bool operator==(const Scalar &s) const { return value == s; }
412  inline bool operator!=(const Scalar &s) const { return value != s; }
413 
415  // ======================================================================
416 
417  // ======================================================================
419  // ======================================================================
420 
422  static inline DVector2 vector(const Eigen::Matrix<Scalar, 2, 1> &v)
423  {
424  return DVector2(DScalar1(v.x()), DScalar1(v.y()));
425  }
426 
428  static inline DVector3 vector(const Eigen::Matrix<Scalar, 3, 1> &v)
429  {
430  return DVector3(DScalar1(v.x()), DScalar1(v.y()), DScalar1(v.z()));
431  }
432 
433 #if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
435  static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v)
436  {
437  return DVector2(DScalar1(v.x), DScalar1(v.y));
438  }
439 
441  static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p)
442  {
443  return DVector2(DScalar1(p.x), DScalar1(p.y));
444  }
445 
447  static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v)
448  {
449  return DVector3(DScalar1(v.x), DScalar1(v.y), DScalar1(v.z));
450  }
451 
453  static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p)
454  {
455  return DVector3(DScalar1(p.x), DScalar1(p.y), DScalar1(p.z));
456  }
457 #endif
458 
460  // ======================================================================
461 protected:
464 };
465 
466 template <typename Scalar, typename VecType>
467 std::ostream &operator<<(std::ostream &out, const DScalar1<Scalar, VecType> &s)
468 {
469  out << "[" << s.getValue()
470  << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
471  << "]";
472  return out;
473 }
474 
498 template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>,
499  typename _Hessian = Eigen::Matrix<_Scalar, Eigen::Dynamic, Eigen::Dynamic>>
500 struct DScalar2 : public DiffScalarBase
501 {
502 public:
503  typedef _Scalar Scalar;
504  typedef _Gradient Gradient;
505  typedef _Hessian Hessian;
506  typedef Eigen::Matrix<DScalar2, 2, 1> DVector2;
507  typedef Eigen::Matrix<DScalar2, 3, 1> DVector3;
508 
509  // ======================================================================
511  // ======================================================================
512 
514  explicit DScalar2(Scalar value_ = (Scalar)0) : value(value_)
515  {
516  size_t variableCount = getVariableCount();
517 
518  grad.resize(variableCount);
519  grad.setZero();
520  hess.resize(variableCount, variableCount);
521  hess.setZero();
522  }
523 
525  DScalar2(size_t index, const Scalar &value_)
526  : value(value_)
527  {
528  size_t variableCount = getVariableCount();
529 
530  grad.resize(variableCount);
531  grad.setZero();
532  grad(index) = 1;
533  hess.resize(variableCount, variableCount);
534  hess.setZero();
535  }
536 
538  DScalar2(Scalar value_, const Gradient &grad_, const Hessian &hess_)
539  : value(value_), grad(grad_), hess(hess_) {}
540 
542  DScalar2(const DScalar2 &s)
543  : value(s.value), grad(s.grad), hess(s.hess) {}
544 
545  inline const Scalar &getValue() const { return value; }
546  inline const Gradient &getGradient() const { return grad; }
547  inline const Hessian &getHessian() const { return hess; }
548 
549  // ======================================================================
551  // ======================================================================
552  friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
553  {
554  return DScalar2(lhs.value + rhs.value,
555  lhs.grad + rhs.grad, lhs.hess + rhs.hess);
556  }
557 
558  friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs)
559  {
560  return DScalar2(lhs.value + rhs, lhs.grad, lhs.hess);
561  }
562 
563  friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs)
564  {
565  return DScalar2(rhs.value + lhs, rhs.grad, rhs.hess);
566  }
567 
568  inline DScalar2 &operator+=(const DScalar2 &s)
569  {
570  value += s.value;
571  grad += s.grad;
572  hess += s.hess;
573  return *this;
574  }
575 
576  inline DScalar2 &operator+=(const Scalar &v)
577  {
578  value += v;
579  return *this;
580  }
581 
583  // ======================================================================
584 
585  // ======================================================================
587  // ======================================================================
588 
589  friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs)
590  {
591  return DScalar2(lhs.value - rhs.value, lhs.grad - rhs.grad, lhs.hess - rhs.hess);
592  }
593 
594  friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs)
595  {
596  return DScalar2(lhs.value - rhs, lhs.grad, lhs.hess);
597  }
598 
599  friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
600  {
601  return DScalar2(lhs - rhs.value, -rhs.grad, -rhs.hess);
602  }
603 
604  friend DScalar2 operator-(const DScalar2 &s)
605  {
606  return DScalar2(-s.value, -s.grad, -s.hess);
607  }
608 
609  inline DScalar2 &operator-=(const DScalar2 &s)
610  {
611  value -= s.value;
612  grad -= s.grad;
613  hess -= s.hess;
614  return *this;
615  }
616 
617  inline DScalar2 &operator-=(const Scalar &v)
618  {
619  value -= v;
620  return *this;
621  }
623  // ======================================================================
624 
625  // ======================================================================
627  // ======================================================================
628  friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs)
629  {
630  if (rhs == 0)
631  throw std::runtime_error("DScalar2: Division by zero!");
632  Scalar inv = 1.0f / rhs;
633  return DScalar2(lhs.value * inv, lhs.grad * inv, lhs.hess * inv);
634  }
635 
636  friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs)
637  {
638  return lhs * inverse(rhs);
639  }
640 
641  friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
642  {
643  return lhs * inverse(rhs);
644  }
645 
646  friend DScalar2 inverse(const DScalar2 &s)
647  {
648  Scalar valueSqr = s.value * s.value,
649  valueCub = valueSqr * s.value,
650  invValueSqr = (Scalar)1 / valueSqr;
651 
652  // vn = 1/v
653  DScalar2 result((Scalar)1 / s.value);
654 
655  // Dvn = -1/(v^2) Dv
656  result.grad = s.grad * -invValueSqr;
657 
658  // D^2vn = -1/(v^2) D^2v + 2/(v^3) Dv Dv^T
659  result.hess = s.hess * -invValueSqr;
660  result.hess += s.grad * s.grad.transpose()
661  * ((Scalar)2 / valueCub);
662 
663  return result;
664  }
665 
666  inline DScalar2 &operator/=(const Scalar &v)
667  {
668  value /= v;
669  grad /= v;
670  hess /= v;
671  return *this;
672  }
674  // ======================================================================
675 
676  // ======================================================================
678  // ======================================================================
679  friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs)
680  {
681  return DScalar2(lhs.value * rhs, lhs.grad * rhs, lhs.hess * rhs);
682  }
683 
684  friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs)
685  {
686  return DScalar2(rhs.value * lhs, rhs.grad * lhs, rhs.hess * lhs);
687  }
688 
689  friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs)
690  {
691  DScalar2 result(lhs.value * rhs.value);
692 
694  result.grad = rhs.grad * lhs.value + lhs.grad * rhs.value;
695 
696  // (i,j) = g*F_xixj + g*G_xixj + F_xi*G_xj + F_xj*G_xi
697  result.hess = rhs.hess * lhs.value;
698  result.hess += lhs.hess * rhs.value;
699  result.hess += lhs.grad * rhs.grad.transpose();
700  result.hess += rhs.grad * lhs.grad.transpose();
701 
702  return result;
703  }
704 
705  inline DScalar2 &operator*=(const Scalar &v)
706  {
707  value *= v;
708  grad *= v;
709  hess *= v;
710  return *this;
711  }
712 
714  // ======================================================================
715 
716  // ======================================================================
718  // ======================================================================
719 
720  friend DScalar2 abs(const DScalar2 &s)
721  {
722  return s.value < 0? -s: s;
723  }
724 
725  friend DScalar2 sqrt(const DScalar2 &s)
726  {
727  Scalar sqrtVal = std::sqrt(s.value),
728  temp = (Scalar)1 / ((Scalar)2 * sqrtVal);
729 
730  // vn = sqrt(v)
731  DScalar2 result(sqrtVal);
732 
733  // Dvn = 1/(2 sqrt(v)) Dv
734  result.grad = s.grad * temp;
735 
736  // D^2vn = 1/(2 sqrt(v)) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
737  result.hess = s.hess * temp;
738  result.hess += s.grad * s.grad.transpose()
739  * (-(Scalar)1 / ((Scalar)4 * s.value * sqrtVal));
740 
741  return result;
742  }
743 
744  friend DScalar2 pow(const DScalar2 &s, const Scalar &a)
745  {
746  Scalar powVal = std::pow(s.value, a),
747  temp = a * std::pow(s.value, a - 1);
748  // vn = v ^ a
749  DScalar2 result(powVal);
750 
751  // Dvn = a*v^(a-1) * Dv
752  result.grad = s.grad * temp;
753 
754  // D^2vn = a*v^(a-1) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
755  result.hess = s.hess * temp;
756  result.hess += s.grad * s.grad.transpose()
757  * (a * (a - 1) * std::pow(s.value, a - 2));
758 
759  return result;
760  }
761 
762  friend DScalar2 exp(const DScalar2 &s)
763  {
764  Scalar expVal = std::exp(s.value);
765 
766  // vn = exp(v)
767  DScalar2 result(expVal);
768 
769  // Dvn = exp(v) * Dv
770  result.grad = s.grad * expVal;
771 
772  // D^2vn = exp(v) * Dv*Dv^T + exp(v) * D^2v
773  result.hess = (s.grad * s.grad.transpose()
774  + s.hess)
775  * expVal;
776 
777  return result;
778  }
779 
780  friend DScalar2 log(const DScalar2 &s)
781  {
782  Scalar logVal = std::log(s.value);
783 
784  // vn = log(v)
785  DScalar2 result(logVal);
786 
787  // Dvn = Dv / v
788  result.grad = s.grad / s.value;
789 
790  // D^2vn = (v*D^2v - Dv*Dv^T)/(v^2)
791  result.hess = s.hess / s.value - (s.grad * s.grad.transpose() / (s.value * s.value));
792 
793  return result;
794  }
795 
796  friend DScalar2 sin(const DScalar2 &s)
797  {
798  Scalar sinVal = std::sin(s.value),
799  cosVal = std::cos(s.value);
800 
801  // vn = sin(v)
802  DScalar2 result(sinVal);
803 
804  // Dvn = cos(v) * Dv
805  result.grad = s.grad * cosVal;
806 
807  // D^2vn = -sin(v) * Dv*Dv^T + cos(v) * Dv^2
808  result.hess = s.hess * cosVal;
809  result.hess += s.grad * s.grad.transpose() * -sinVal;
810 
811  return result;
812  }
813 
814  friend DScalar2 cos(const DScalar2 &s)
815  {
816  Scalar sinVal = std::sin(s.value),
817  cosVal = std::cos(s.value);
818  // vn = cos(v)
819  DScalar2 result(cosVal);
820 
821  // Dvn = -sin(v) * Dv
822  result.grad = s.grad * -sinVal;
823 
824  // D^2vn = -cos(v) * Dv*Dv^T - sin(v) * Dv^2
825  result.hess = s.hess * -sinVal;
826  result.hess += s.grad * s.grad.transpose() * -cosVal;
827 
828  return result;
829  }
830 
831  friend DScalar2 acos(const DScalar2 &s)
832  {
833  if (std::abs(s.value) >= 1)
834  throw std::runtime_error("acos: Expected a value in (-1, 1)");
835 
836  Scalar temp = -std::sqrt((Scalar)1 - s.value * s.value);
837 
838  // vn = acos(v)
839  DScalar2 result(std::acos(s.value));
840 
841  // Dvn = -1/sqrt(1-v^2) * Dv
842  result.grad = s.grad * ((Scalar)1 / temp);
843 
844  // D^2vn = -1/sqrt(1-v^2) * D^2v - v/[(1-v^2)^(3/2)] * Dv*Dv^T
845  result.hess = s.hess * ((Scalar)1 / temp);
846  result.hess += s.grad * s.grad.transpose()
847  * s.value / (temp * temp * temp);
848 
849  return result;
850  }
851 
852  friend DScalar2 asin(const DScalar2 &s)
853  {
854  if (std::abs(s.value) >= 1)
855  throw std::runtime_error("asin: Expected a value in (-1, 1)");
856 
857  Scalar temp = std::sqrt((Scalar)1 - s.value * s.value);
858 
859  // vn = asin(v)
860  DScalar2 result(std::asin(s.value));
861 
862  // Dvn = 1/sqrt(1-v^2) * Dv
863  result.grad = s.grad * ((Scalar)1 / temp);
864 
865  // D^2vn = 1/sqrt(1-v*v) * D^2v + v/[(1-v^2)^(3/2)] * Dv*Dv^T
866  result.hess = s.hess * ((Scalar)1 / temp);
867  result.hess += s.grad * s.grad.transpose()
868  * s.value / (temp * temp * temp);
869 
870  return result;
871  }
872 
873  friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x)
874  {
875  // vn = atan2(y, x)
876  DScalar2 result(std::atan2(y.value, x.value));
877 
878  // Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
879  Scalar denom = x.value * x.value + y.value * y.value,
880  denomSqr = denom * denom;
881  result.grad = y.grad * (x.value / denom)
882  - x.grad * (y.value / denom);
883 
884  // D^2vn = (Dy*Dx^T + xD^2y - Dx*Dy^T - yD^2x) / (x^2+y^2)
885  // - [(x*Dy - y*Dx) * (2*x*Dx + 2*y*Dy)^T] / (x^2+y^2)^2
886  result.hess = (y.hess * x.value
887  + y.grad * x.grad.transpose()
888  - x.hess * y.value
889  - x.grad * y.grad.transpose())
890  / denom;
891 
892  result.hess -=
893  (y.grad * (x.value / denomSqr) - x.grad * (y.value / denomSqr)) * (x.grad * ((Scalar)2 * x.value) + y.grad * ((Scalar)2 * y.value)).transpose();
894 
895  return result;
896  }
897 
899  // ======================================================================
900 
901  // ======================================================================
903  // ======================================================================
904 
905  inline void operator=(const DScalar2 &s)
906  {
907  value = s.value;
908  grad = s.grad;
909  hess = s.hess;
910  }
911  inline void operator=(const Scalar &v)
912  {
913  value = v;
914  grad = Gradient::Zero(getVariableCount());
915  hess = Hessian::Zero(getVariableCount(), getVariableCount());
916  }
917  inline bool operator<(const DScalar2 &s) const { return value < s.value; }
918  inline bool operator<=(const DScalar2 &s) const { return value <= s.value; }
919  inline bool operator>(const DScalar2 &s) const { return value > s.value; }
920  inline bool operator>=(const DScalar2 &s) const { return value >= s.value; }
921  inline bool operator!=(const DScalar2 &s) const { return value != s.value; }
922 
923  inline bool operator<(const Scalar &s) const { return value < s; }
924  inline bool operator<=(const Scalar &s) const { return value <= s; }
925  inline bool operator>(const Scalar &s) const { return value > s; }
926  inline bool operator>=(const Scalar &s) const { return value >= s; }
927  inline bool operator==(const Scalar &s) const { return value == s; }
928  inline bool operator!=(const Scalar &s) const { return value != s; }
929 
931  // ======================================================================
932 
933  // ======================================================================
935  // ======================================================================
936 
937 #if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
939  static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v)
940  {
941  return DVector2(DScalar2(v.x), DScalar2(v.y));
942  }
943 
945  static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p)
946  {
947  return DVector2(DScalar2(p.x), DScalar2(p.y));
948  }
949 
951  static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v)
952  {
953  return DVector3(DScalar2(v.x), DScalar2(v.y), DScalar2(v.z));
954  }
955 
957  static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p)
958  {
959  return DVector3(DScalar2(p.x), DScalar2(p.y), DScalar2(p.z));
960  }
961 #endif
962 
964  static inline DVector2 vector(const Eigen::Matrix<Scalar, 2, 1> &v)
965  {
966  return DVector2(DScalar2(v.x()), DScalar2(v.y()));
967  }
968 
970  static inline DVector3 vector(const Eigen::Matrix<Scalar, 3, 1> &v)
971  {
972  return DVector3(DScalar2(v.x()), DScalar2(v.y()), DScalar2(v.z()));
973  }
974 
976  // ======================================================================
977 protected:
981 };
982 
983 template <typename Scalar, typename VecType, typename MatType>
984 std::ostream &operator<<(std::ostream &out, const DScalar2<Scalar, VecType, MatType> &s)
985 {
986  out << "[" << s.getValue()
987  << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
988  << ", hess=" << s.getHessian().format(Eigen::IOFormat(4, 0, ", ", "; ", "", "", "[", "]"))
989  << "]";
990  return out;
991 }
992 
993 // clang-format on
994 
995 namespace std {
996 
997 template <typename _Scalar, typename _Gradient>
998 class numeric_limits<DScalar1<_Scalar, _Gradient>>
999 {
1000 public:
1001  static const bool is_specialized = std::numeric_limits<_Scalar>::is_specialized;
1002  static const bool is_signed = std::numeric_limits<_Scalar>::is_signed;
1003  static const bool is_integer = std::numeric_limits<_Scalar>::is_integer;
1004  static const bool is_exact = std::numeric_limits<_Scalar>::is_exact;
1005  static const int radix = std::numeric_limits<_Scalar>::radix;
1006  static const bool has_infinity = std::numeric_limits<_Scalar>::has_infinity;
1007  static const bool has_quiet_NaN = std::numeric_limits<_Scalar>::has_quiet_NaN;
1008  static const bool has_signaling_NaN = std::numeric_limits<_Scalar>::has_signaling_NaN;
1009  static const bool is_iec559 = std::numeric_limits<_Scalar>::is_iec559;
1010  static const bool is_bounded = std::numeric_limits<_Scalar>::is_bounded;
1011  static const bool is_modulo = std::numeric_limits<_Scalar>::is_modulo;
1012  static const bool traps = std::numeric_limits<_Scalar>::traps;
1013  static const bool tinyness_before = std::numeric_limits<_Scalar>::tinyness_before;
1014  static const std::float_denorm_style has_denorm = std::numeric_limits<_Scalar>::has_denorm;
1015  static const bool has_denorm_loss = std::numeric_limits<_Scalar>::has_denorm_loss;
1016  static const int min_exponent = std::numeric_limits<_Scalar>::min_exponent;
1017  static const int max_exponent = std::numeric_limits<_Scalar>::max_exponent;
1018  static const int min_exponent10 = std::numeric_limits<_Scalar>::min_exponent10;
1019  static const int max_exponent10 = std::numeric_limits<_Scalar>::max_exponent10;
1020  static const std::float_round_style round_style = std::numeric_limits<_Scalar>::round_style;
1021  static const int digits = std::numeric_limits<_Scalar>::digits;
1022  static const int digits10 = std::numeric_limits<_Scalar>::digits10;
1023  static const int max_digits10 = std::numeric_limits<_Scalar>::max_digits10;
1024 
1025  static constexpr _Scalar min() { return std::numeric_limits<_Scalar>::min(); }
1026 
1027  static constexpr _Scalar max() { return std::numeric_limits<_Scalar>::max(); }
1028 
1029  static constexpr _Scalar lowest() { return std::numeric_limits<_Scalar>::lowest(); }
1030 
1031  static constexpr _Scalar epsilon() { return std::numeric_limits<_Scalar>::epsilon(); }
1032 
1033  static constexpr _Scalar round_error() { return std::numeric_limits<_Scalar>::round_error(); }
1034 
1035  static constexpr _Scalar infinity() { return std::numeric_limits<_Scalar>::infinity(); }
1036 
1037  static constexpr _Scalar quiet_NaN() { return std::numeric_limits<_Scalar>::quiet_NaN(); }
1038 
1039  static constexpr _Scalar signaling_NaN()
1040  {
1041  return std::numeric_limits<_Scalar>::signaling_NaN();
1042  }
1043 
1044  static constexpr _Scalar denorm_min() { return std::numeric_limits<_Scalar>::denorm_min(); }
1045 };
1046 
1047 template <typename _Scalar, typename _Gradient, typename _Hessian>
1048 class numeric_limits<DScalar2<_Scalar, _Gradient, _Hessian>>
1049 {
1050 public:
1051  static const bool is_specialized = std::numeric_limits<_Scalar>::is_specialized;
1052  static const bool is_signed = std::numeric_limits<_Scalar>::is_signed;
1053  static const bool is_integer = std::numeric_limits<_Scalar>::is_integer;
1054  static const bool is_exact = std::numeric_limits<_Scalar>::is_exact;
1055  static const int radix = std::numeric_limits<_Scalar>::radix;
1056  static const bool has_infinity = std::numeric_limits<_Scalar>::has_infinity;
1057  static const bool has_quiet_NaN = std::numeric_limits<_Scalar>::has_quiet_NaN;
1058  static const bool has_signaling_NaN = std::numeric_limits<_Scalar>::has_signaling_NaN;
1059  static const bool is_iec559 = std::numeric_limits<_Scalar>::is_iec559;
1060  static const bool is_bounded = std::numeric_limits<_Scalar>::is_bounded;
1061  static const bool is_modulo = std::numeric_limits<_Scalar>::is_modulo;
1062  static const bool traps = std::numeric_limits<_Scalar>::traps;
1063  static const bool tinyness_before = std::numeric_limits<_Scalar>::tinyness_before;
1064  static const std::float_denorm_style has_denorm = std::numeric_limits<_Scalar>::has_denorm;
1065  static const bool has_denorm_loss = std::numeric_limits<_Scalar>::has_denorm_loss;
1066  static const int min_exponent = std::numeric_limits<_Scalar>::min_exponent;
1067  static const int max_exponent = std::numeric_limits<_Scalar>::max_exponent;
1068  static const int min_exponent10 = std::numeric_limits<_Scalar>::min_exponent10;
1069  static const int max_exponent10 = std::numeric_limits<_Scalar>::max_exponent10;
1070  static const std::float_round_style round_style = std::numeric_limits<_Scalar>::round_style;
1071  static const int digits = std::numeric_limits<_Scalar>::digits;
1072  static const int digits10 = std::numeric_limits<_Scalar>::digits10;
1073  static const int max_digits10 = std::numeric_limits<_Scalar>::max_digits10;
1074 
1075  static constexpr _Scalar min() { return std::numeric_limits<_Scalar>::min(); }
1076 
1077  static constexpr _Scalar max() { return std::numeric_limits<_Scalar>::max(); }
1078 
1079  static constexpr _Scalar lowest() { return std::numeric_limits<_Scalar>::lowest(); }
1080 
1081  static constexpr _Scalar epsilon() { return std::numeric_limits<_Scalar>::epsilon(); }
1082 
1083  static constexpr _Scalar round_error() { return std::numeric_limits<_Scalar>::round_error(); }
1084 
1085  static constexpr _Scalar infinity() { return std::numeric_limits<_Scalar>::infinity(); }
1086 
1087  static constexpr _Scalar quiet_NaN() { return std::numeric_limits<_Scalar>::quiet_NaN(); }
1088 
1089  static constexpr _Scalar signaling_NaN()
1090  {
1091  return std::numeric_limits<_Scalar>::signaling_NaN();
1092  }
1093 
1094  static constexpr _Scalar denorm_min() { return std::numeric_limits<_Scalar>::denorm_min(); }
1095 };
1096 
1097 } // namespace std
1098 
1099 #endif /* __AUTODIFF_H */
std::ostream & operator<<(std::ostream &out, const DScalar1< Scalar, VecType > &s)
Definition: autodiff.h:467
Definition: autodiff.h:995
Rational abs(const Rational &r0)
Definition: Rational.cpp:328
Rational pow(const Rational &x, int p)
Definition: Rational.cpp:166
Automatic differentiation scalar with first-order derivatives.
Definition: autodiff.h:115
friend DScalar1 sin(const DScalar1 &s)
Definition: autodiff.h:341
DScalar1(const DScalar1 &s)
Copy constructor.
Definition: autodiff.h:149
DScalar1 & operator+=(const DScalar1 &s)
Definition: autodiff.h:173
friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
Definition: autodiff.h:377
DScalar1 & operator-=(const DScalar1 &s)
Definition: autodiff.h:213
friend DScalar1 operator-(const DScalar1 &s)
Definition: autodiff.h:208
friend DScalar1 cos(const DScalar1 &s)
Definition: autodiff.h:347
bool operator<=(const Scalar &s) const
Definition: autodiff.h:408
DScalar1 & operator-=(const Scalar &v)
Definition: autodiff.h:220
friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:271
friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:244
bool operator==(const Scalar &s) const
Definition: autodiff.h:411
_Scalar Scalar
Definition: autodiff.h:117
friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:281
friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:193
bool operator<(const DScalar1 &s) const
Definition: autodiff.h:403
bool operator>=(const Scalar &s) const
Definition: autodiff.h:410
friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:198
const Gradient & getGradient() const
Definition: autodiff.h:153
bool operator>(const Scalar &s) const
Definition: autodiff.h:409
bool operator!=(const Scalar &s) const
Definition: autodiff.h:412
friend DScalar1 inverse(const DScalar1 &s)
Definition: autodiff.h:249
friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:231
friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:239
DScalar1(Scalar value_, const Gradient &grad_)
Construct a scalar associated with the given gradient.
Definition: autodiff.h:145
friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:276
static DVector2 vector(const Eigen::Matrix< Scalar, 2, 1 > &v)
Initialize a constant two-dimensional vector.
Definition: autodiff.h:422
Eigen::Matrix< DScalar1, 2, 1 > DVector2
Definition: autodiff.h:119
static DVector3 vector(const Eigen::Matrix< Scalar, 3, 1 > &v)
Create a constant three-dimensional vector.
Definition: autodiff.h:428
bool operator>=(const DScalar1 &s) const
Definition: autodiff.h:406
friend DScalar1 asin(const DScalar1 &s)
Definition: autodiff.h:365
friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs)
Definition: autodiff.h:163
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:135
_Gradient Gradient
Definition: autodiff.h:118
friend DScalar1 pow(const DScalar1 &s, const Scalar &a)
Definition: autodiff.h:317
Scalar value
Definition: autodiff.h:462
Gradient grad
Definition: autodiff.h:463
bool operator<=(const DScalar1 &s) const
Definition: autodiff.h:404
DScalar1 & operator/=(const Scalar &v)
Definition: autodiff.h:258
DScalar1(Scalar value_=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:127
friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:203
friend DScalar1 abs(const DScalar1 &s)
Definition: autodiff.h:302
friend DScalar1 exp(const DScalar1 &s)
Definition: autodiff.h:325
DScalar1 & operator+=(const Scalar &v)
Definition: autodiff.h:180
Eigen::Matrix< DScalar1, 3, 1 > DVector3
Definition: autodiff.h:120
friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs)
Definition: autodiff.h:168
friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs)
Definition: autodiff.h:158
DScalar1 & operator*=(const Scalar &v)
Definition: autodiff.h:288
void operator=(const Scalar &v)
Definition: autodiff.h:398
friend DScalar1 acos(const DScalar1 &s)
Definition: autodiff.h:353
bool operator>(const DScalar1 &s) const
Definition: autodiff.h:405
friend DScalar1 sqrt(const DScalar1 &s)
Definition: autodiff.h:307
const Scalar & getValue() const
Definition: autodiff.h:152
friend DScalar1 log(const DScalar1 &s)
Definition: autodiff.h:333
bool operator<(const Scalar &s) const
Definition: autodiff.h:407
void operator=(const DScalar1 &s)
Definition: autodiff.h:393
Automatic differentiation scalar with first- and second-order derivatives.
Definition: autodiff.h:501
const Scalar & getValue() const
Definition: autodiff.h:545
DScalar2 & operator+=(const Scalar &v)
Definition: autodiff.h:576
DScalar2 & operator+=(const DScalar2 &s)
Definition: autodiff.h:568
Eigen::Matrix< DScalar2, 2, 1 > DVector2
Definition: autodiff.h:506
bool operator<=(const Scalar &s) const
Definition: autodiff.h:924
Hessian hess
Definition: autodiff.h:980
bool operator<(const Scalar &s) const
Definition: autodiff.h:923
_Hessian Hessian
Definition: autodiff.h:505
friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x)
Definition: autodiff.h:873
friend DScalar2 sin(const DScalar2 &s)
Definition: autodiff.h:796
bool operator>(const Scalar &s) const
Definition: autodiff.h:925
bool operator>(const DScalar2 &s) const
Definition: autodiff.h:919
friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:552
bool operator<(const DScalar2 &s) const
Definition: autodiff.h:917
friend DScalar2 inverse(const DScalar2 &s)
Definition: autodiff.h:646
friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:679
void operator=(const Scalar &v)
Definition: autodiff.h:911
bool operator==(const Scalar &s) const
Definition: autodiff.h:927
friend DScalar2 cos(const DScalar2 &s)
Definition: autodiff.h:814
friend DScalar2 acos(const DScalar2 &s)
Definition: autodiff.h:831
DScalar2(Scalar value_, const Gradient &grad_, const Hessian &hess_)
Construct a scalar associated with the given gradient and Hessian.
Definition: autodiff.h:538
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:525
bool operator>=(const Scalar &s) const
Definition: autodiff.h:926
const Hessian & getHessian() const
Definition: autodiff.h:547
DScalar2(const DScalar2 &s)
Copy constructor.
Definition: autodiff.h:542
bool operator>=(const DScalar2 &s) const
Definition: autodiff.h:920
friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:589
static DVector2 vector(const Eigen::Matrix< Scalar, 2, 1 > &v)
Initialize a constant two-dimensional vector.
Definition: autodiff.h:964
Eigen::Matrix< DScalar2, 3, 1 > DVector3
Definition: autodiff.h:507
friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:558
friend DScalar2 exp(const DScalar2 &s)
Definition: autodiff.h:762
friend DScalar2 log(const DScalar2 &s)
Definition: autodiff.h:780
Scalar value
Definition: autodiff.h:978
friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:628
DScalar2(Scalar value_=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition: autodiff.h:514
bool operator!=(const DScalar2 &s) const
Definition: autodiff.h:921
friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:689
void operator=(const DScalar2 &s)
Definition: autodiff.h:905
friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:563
friend DScalar2 abs(const DScalar2 &s)
Definition: autodiff.h:720
DScalar2 & operator/=(const Scalar &v)
Definition: autodiff.h:666
bool operator<=(const DScalar2 &s) const
Definition: autodiff.h:918
Gradient grad
Definition: autodiff.h:979
_Gradient Gradient
Definition: autodiff.h:504
friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:636
friend DScalar2 sqrt(const DScalar2 &s)
Definition: autodiff.h:725
friend DScalar2 operator-(const DScalar2 &s)
Definition: autodiff.h:604
const Gradient & getGradient() const
Definition: autodiff.h:546
DScalar2 & operator-=(const Scalar &v)
Definition: autodiff.h:617
friend DScalar2 asin(const DScalar2 &s)
Definition: autodiff.h:852
friend DScalar2 pow(const DScalar2 &s, const Scalar &a)
Definition: autodiff.h:744
friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:684
static DVector3 vector(const Eigen::Matrix< Scalar, 3, 1 > &v)
Create a constant three-dimensional vector.
Definition: autodiff.h:970
friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
Definition: autodiff.h:599
DScalar2 & operator-=(const DScalar2 &s)
Definition: autodiff.h:609
bool operator!=(const Scalar &s) const
Definition: autodiff.h:928
friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
Definition: autodiff.h:641
DScalar2 & operator*=(const Scalar &v)
Definition: autodiff.h:705
_Scalar Scalar
Definition: autodiff.h:503
friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs)
Definition: autodiff.h:594
Base class of all automatic differentiation types.
Definition: autodiff.h:44
static thread_local size_t m_variableCount
Definition: autodiff.h:76
static size_t getVariableCount()
Get the variable count used by the automatic differentiation layer.
Definition: autodiff.h:63
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Definition: autodiff.h:57