PolyFEM
Loading...
Searching...
No Matches
autodiff.h
Go to the documentation of this file.
1
23#ifndef __AUTODIFF_H
24#define __AUTODIFF_H
25
26#ifndef EIGEN_DONT_PARALLELIZE
27#define EIGEN_DONT_PARALLELIZE
28#endif
29
30#include <Eigen/Core>
31#include <cmath>
32#include <stdexcept>
33
41{
42 // ======================================================================
44 // ======================================================================
45
54 static inline void setVariableCount(size_t value)
55 {
56 m_variableCount = value;
57 }
58
60 static inline size_t getVariableCount()
61 {
62 return m_variableCount;
63 }
64
66 // ======================================================================
67
68 // #ifdef WIN32
69 // static __declspec(thread) size_t m_variableCount;
70 // #else
71 // static __thread size_t m_variableCount;
72 // #endif
73 static thread_local size_t m_variableCount;
74};
75
76// #ifdef WIN32
77// #define DECLARE_DIFFSCALAR_BASE()
78// __declspec(thread) size_t DiffScalarBase::m_variableCount = 0
79// #else
80// #define DECLARE_DIFFSCALAR_BASE()
81// __thread size_t DiffScalarBase::m_variableCount = 0
82// #endif
83
84#define DECLARE_DIFFSCALAR_BASE() \
85 thread_local size_t DiffScalarBase::m_variableCount = 0
86
110template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>>
112{
113public:
114 typedef _Scalar Scalar;
115 typedef _Gradient Gradient;
116 typedef Eigen::Matrix<DScalar1, 2, 1> DVector2;
117 typedef Eigen::Matrix<DScalar1, 3, 1> DVector3;
118
119 // ======================================================================
121 // ======================================================================
122
124 explicit DScalar1(Scalar value_ = (Scalar)0) : value(value_)
125 {
126 size_t variableCount = getVariableCount();
127 grad.resize(variableCount);
128 grad.setZero();
129 }
130
132 DScalar1(size_t index, const Scalar &value_)
133 : value(value_)
134 {
135 size_t variableCount = getVariableCount();
136 grad.resize(variableCount);
137 grad.setZero();
138 grad(index) = 1;
139 }
140
142 DScalar1(Scalar value_, const Gradient &grad_)
143 : value(value_), grad(grad_) {}
144
147 : value(s.value), grad(s.grad) {}
148
149 inline const Scalar &getValue() const { return value; }
150 inline const Gradient &getGradient() const { return grad; }
151
152 // ======================================================================
154 // ======================================================================
155 friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs)
156 {
157 return DScalar1(lhs.value + rhs.value, lhs.grad + rhs.grad);
158 }
159
160 friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs)
161 {
162 return DScalar1(lhs.value + rhs, lhs.grad);
163 }
164
165 friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs)
166 {
167 return DScalar1(rhs.value + lhs, rhs.grad);
168 }
169
170 inline DScalar1 &operator+=(const DScalar1 &s)
171 {
172 value += s.value;
173 grad += s.grad;
174 return *this;
175 }
176
177 inline DScalar1 &operator+=(const Scalar &v)
178 {
179 value += v;
180 return *this;
181 }
182
184 // ======================================================================
185
186 // ======================================================================
188 // ======================================================================
189
190 friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs)
191 {
192 return DScalar1(lhs.value - rhs.value, lhs.grad - rhs.grad);
193 }
194
195 friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
196 {
197 return DScalar1(lhs.value - rhs, lhs.grad);
198 }
199
200 friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs)
201 {
202 return DScalar1(lhs - rhs.value, -rhs.grad);
203 }
204
205 friend DScalar1 operator-(const DScalar1 &s)
206 {
207 return DScalar1(-s.value, -s.grad);
208 }
209
210 inline DScalar1 &operator-=(const DScalar1 &s)
211 {
212 value -= s.value;
213 grad -= s.grad;
214 return *this;
215 }
216
217 inline DScalar1 &operator-=(const Scalar &v)
218 {
219 value -= v;
220 return *this;
221 }
223 // ======================================================================
224
225 // ======================================================================
227 // ======================================================================
228 friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs)
229 {
230 if (rhs == 0)
231 throw std::runtime_error("DScalar1: Division by zero!");
232 Scalar inv = 1.0f / rhs;
233 return DScalar1(lhs.value * inv, lhs.grad * inv);
234 }
235
236 friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs)
237 {
238 return lhs * inverse(rhs);
239 }
240
241 friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs)
242 {
243 return lhs * inverse(rhs);
244 }
245
246 friend DScalar1 inverse(const DScalar1 &s)
247 {
248 Scalar valueSqr = s.value * s.value,
249 invValueSqr = (Scalar)1 / valueSqr;
250
251 // vn = 1/v, Dvn = -1/(v^2) Dv
252 return DScalar1((Scalar)1 / s.value, s.grad * -invValueSqr);
253 }
254
255 inline DScalar1 &operator/=(const Scalar &v)
256 {
257 value /= v;
258 grad /= v;
259 return *this;
260 }
261
263 // ======================================================================
264
265 // ======================================================================
267 // ======================================================================
268 inline friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
269 {
270 return DScalar1(lhs.value * rhs, lhs.grad * rhs);
271 }
272
273 inline friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs)
274 {
275 return DScalar1(rhs.value * lhs, rhs.grad * lhs);
276 }
277
278 inline friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs)
279 {
280 // Product rule
281 return DScalar1(lhs.value * rhs.value,
282 rhs.grad * lhs.value + lhs.grad * rhs.value);
283 }
284
285 inline DScalar1 &operator*=(const Scalar &v)
286 {
287 value *= v;
288 grad *= v;
289 return *this;
290 }
291
293 // ======================================================================
294
295 // ======================================================================
297 // ======================================================================
298
299 friend DScalar1 sqrt(const DScalar1 &s)
300 {
301 Scalar sqrtVal = std::sqrt(s.value),
302 temp = (Scalar)1 / ((Scalar)2 * sqrtVal);
303
304 // vn = sqrt(v)
305 // Dvn = 1/(2 sqrt(v)) Dv
306 return DScalar1(sqrtVal, s.grad * temp);
307 }
308
309 friend DScalar1 pow(const DScalar1 &s, const Scalar &a)
310 {
311 Scalar powVal = std::pow(s.value, a),
312 temp = a * std::pow(s.value, a - 1);
313 // vn = v ^ a, Dvn = a*v^(a-1) * Dv
314 return DScalar1(powVal, s.grad * temp);
315 }
316
317 friend DScalar1 exp(const DScalar1 &s)
318 {
319 Scalar expVal = std::exp(s.value);
320
321 // vn = exp(v), Dvn = exp(v) * Dv
322 return DScalar1(expVal, s.grad * expVal);
323 }
324
325 friend DScalar1 log(const DScalar1 &s)
326 {
327 Scalar logVal = std::log(s.value);
328
329 // vn = log(v), Dvn = Dv / v
330 return DScalar1(logVal, s.grad / s.value);
331 }
332
333 friend DScalar1 sin(const DScalar1 &s)
334 {
335 // vn = sin(v), Dvn = cos(v) * Dv
336 return DScalar1(std::sin(s.value), s.grad * std::cos(s.value));
337 }
338
339 friend DScalar1 cos(const DScalar1 &s)
340 {
341 // vn = cos(v), Dvn = -sin(v) * Dv
342 return DScalar1(std::cos(s.value), s.grad * -std::sin(s.value));
343 }
344
345 friend DScalar1 acos(const DScalar1 &s)
346 {
347 if (std::abs(s.value) >= 1)
348 throw std::runtime_error("acos: Expected a value in (-1, 1)");
349
350 Scalar temp = -std::sqrt((Scalar)1 - s.value * s.value);
351
352 // vn = acos(v), Dvn = -1/sqrt(1-v^2) * Dv
353 return DScalar1(std::acos(s.value),
354 s.grad * ((Scalar)1 / temp));
355 }
356
357 friend DScalar1 asin(const DScalar1 &s)
358 {
359 if (std::abs(s.value) >= 1)
360 throw std::runtime_error("asin: Expected a value in (-1, 1)");
361
362 Scalar temp = std::sqrt((Scalar)1 - s.value * s.value);
363
364 // vn = asin(v), Dvn = 1/sqrt(1-v^2) * Dv
365 return DScalar1(std::asin(s.value),
366 s.grad * ((Scalar)1 / temp));
367 }
368
369 friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
370 {
371 Scalar denom = x.value * x.value + y.value * y.value;
372
373 // vn = atan2(y, x), Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
374 return DScalar1(std::atan2(y.value, x.value),
375 y.grad * (x.value / denom) - x.grad * (y.value / denom));
376 }
377
379 // ======================================================================
380
381 // ======================================================================
383 // ======================================================================
384
385 inline void operator=(const DScalar1 &s)
386 {
387 value = s.value;
388 grad = s.grad;
389 }
390 inline void operator=(const Scalar &v)
391 {
392 value = v;
393 grad.setZero();
394 }
395 inline bool operator<(const DScalar1 &s) const { return value < s.value; }
396 inline bool operator<=(const DScalar1 &s) const { return value <= s.value; }
397 inline bool operator>(const DScalar1 &s) const { return value > s.value; }
398 inline bool operator>=(const DScalar1 &s) const { return value >= s.value; }
399 inline bool operator<(const Scalar &s) const { return value < s; }
400 inline bool operator<=(const Scalar &s) const { return value <= s; }
401 inline bool operator>(const Scalar &s) const { return value > s; }
402 inline bool operator>=(const Scalar &s) const { return value >= s; }
403 inline bool operator==(const Scalar &s) const { return value == s; }
404 inline bool operator!=(const Scalar &s) const { return value != s; }
405
407 // ======================================================================
408
409 // ======================================================================
411 // ======================================================================
412
414 static inline DVector2 vector(const Eigen::Matrix<Scalar, 2, 1> &v)
415 {
416 return DVector2(DScalar1(v.x()), DScalar1(v.y()));
417 }
418
420 static inline DVector3 vector(const Eigen::Matrix<Scalar, 3, 1> &v)
421 {
422 return DVector3(DScalar1(v.x()), DScalar1(v.y()), DScalar1(v.z()));
423 }
424
425#if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
427 static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v)
428 {
429 return DVector2(DScalar1(v.x), DScalar1(v.y));
430 }
431
433 static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p)
434 {
435 return DVector2(DScalar1(p.x), DScalar1(p.y));
436 }
437
439 static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v)
440 {
441 return DVector3(DScalar1(v.x), DScalar1(v.y), DScalar1(v.z));
442 }
443
445 static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p)
446 {
447 return DVector3(DScalar1(p.x), DScalar1(p.y), DScalar1(p.z));
448 }
449#endif
450
452 // ======================================================================
453protected:
456};
457
458template <typename Scalar, typename VecType>
459std::ostream &operator<<(std::ostream &out, const DScalar1<Scalar, VecType> &s)
460{
461 out << "[" << s.getValue()
462 << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
463 << "]";
464 return out;
465}
466
490template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>,
491 typename _Hessian = Eigen::Matrix<_Scalar, Eigen::Dynamic, Eigen::Dynamic>>
493{
494public:
495 typedef _Scalar Scalar;
496 typedef _Gradient Gradient;
497 typedef _Hessian Hessian;
498 typedef Eigen::Matrix<DScalar2, 2, 1> DVector2;
499 typedef Eigen::Matrix<DScalar2, 3, 1> DVector3;
500
501 // ======================================================================
503 // ======================================================================
504
506 explicit DScalar2(Scalar value_ = (Scalar)0) : value(value_)
507 {
508 size_t variableCount = getVariableCount();
509
510 grad.resize(variableCount);
511 grad.setZero();
512 hess.resize(variableCount, variableCount);
513 hess.setZero();
514 }
515
517 DScalar2(size_t index, const Scalar &value_)
518 : value(value_)
519 {
520 size_t variableCount = getVariableCount();
521
522 grad.resize(variableCount);
523 grad.setZero();
524 grad(index) = 1;
525 hess.resize(variableCount, variableCount);
526 hess.setZero();
527 }
528
530 DScalar2(Scalar value_, const Gradient &grad_, const Hessian &hess_)
531 : value(value_), grad(grad_), hess(hess_) {}
532
535 : value(s.value), grad(s.grad), hess(s.hess) {}
536
537 inline const Scalar &getValue() const { return value; }
538 inline const Gradient &getGradient() const { return grad; }
539 inline const Hessian &getHessian() const { return hess; }
540
541 // ======================================================================
543 // ======================================================================
544 friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
545 {
546 return DScalar2(lhs.value + rhs.value,
547 lhs.grad + rhs.grad, lhs.hess + rhs.hess);
548 }
549
550 friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs)
551 {
552 return DScalar2(lhs.value + rhs, lhs.grad, lhs.hess);
553 }
554
555 friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs)
556 {
557 return DScalar2(rhs.value + lhs, rhs.grad, rhs.hess);
558 }
559
560 inline DScalar2 &operator+=(const DScalar2 &s)
561 {
562 value += s.value;
563 grad += s.grad;
564 hess += s.hess;
565 return *this;
566 }
567
568 inline DScalar2 &operator+=(const Scalar &v)
569 {
570 value += v;
571 return *this;
572 }
573
575 // ======================================================================
576
577 // ======================================================================
579 // ======================================================================
580
581 friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs)
582 {
583 return DScalar2(lhs.value - rhs.value, lhs.grad - rhs.grad, lhs.hess - rhs.hess);
584 }
585
586 friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs)
587 {
588 return DScalar2(lhs.value - rhs, lhs.grad, lhs.hess);
589 }
590
591 friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
592 {
593 return DScalar2(lhs - rhs.value, -rhs.grad, -rhs.hess);
594 }
595
596 friend DScalar2 operator-(const DScalar2 &s)
597 {
598 return DScalar2(-s.value, -s.grad, -s.hess);
599 }
600
601 inline DScalar2 &operator-=(const DScalar2 &s)
602 {
603 value -= s.value;
604 grad -= s.grad;
605 hess -= s.hess;
606 return *this;
607 }
608
609 inline DScalar2 &operator-=(const Scalar &v)
610 {
611 value -= v;
612 return *this;
613 }
615 // ======================================================================
616
617 // ======================================================================
619 // ======================================================================
620 friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs)
621 {
622 if (rhs == 0)
623 throw std::runtime_error("DScalar2: Division by zero!");
624 Scalar inv = 1.0f / rhs;
625 return DScalar2(lhs.value * inv, lhs.grad * inv, lhs.hess * inv);
626 }
627
628 friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs)
629 {
630 return lhs * inverse(rhs);
631 }
632
633 friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
634 {
635 return lhs * inverse(rhs);
636 }
637
638 friend DScalar2 inverse(const DScalar2 &s)
639 {
640 Scalar valueSqr = s.value * s.value,
641 valueCub = valueSqr * s.value,
642 invValueSqr = (Scalar)1 / valueSqr;
643
644 // vn = 1/v
645 DScalar2 result((Scalar)1 / s.value);
646
647 // Dvn = -1/(v^2) Dv
648 result.grad = s.grad * -invValueSqr;
649
650 // D^2vn = -1/(v^2) D^2v + 2/(v^3) Dv Dv^T
651 result.hess = s.hess * -invValueSqr;
652 result.hess += s.grad * s.grad.transpose()
653 * ((Scalar)2 / valueCub);
654
655 return result;
656 }
657
658 inline DScalar2 &operator/=(const Scalar &v)
659 {
660 value /= v;
661 grad /= v;
662 hess /= v;
663 return *this;
664 }
666 // ======================================================================
667
668 // ======================================================================
670 // ======================================================================
671 friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs)
672 {
673 return DScalar2(lhs.value * rhs, lhs.grad * rhs, lhs.hess * rhs);
674 }
675
676 friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs)
677 {
678 return DScalar2(rhs.value * lhs, rhs.grad * lhs, rhs.hess * lhs);
679 }
680
681 friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs)
682 {
683 DScalar2 result(lhs.value * rhs.value);
684
686 result.grad = rhs.grad * lhs.value + lhs.grad * rhs.value;
687
688 // (i,j) = g*F_xixj + g*G_xixj + F_xi*G_xj + F_xj*G_xi
689 result.hess = rhs.hess * lhs.value;
690 result.hess += lhs.hess * rhs.value;
691 result.hess += lhs.grad * rhs.grad.transpose();
692 result.hess += rhs.grad * lhs.grad.transpose();
693
694 return result;
695 }
696
697 inline DScalar2 &operator*=(const Scalar &v)
698 {
699 value *= v;
700 grad *= v;
701 hess *= v;
702 return *this;
703 }
704
706 // ======================================================================
707
708 // ======================================================================
710 // ======================================================================
711
712 friend DScalar2 sqrt(const DScalar2 &s)
713 {
714 Scalar sqrtVal = std::sqrt(s.value),
715 temp = (Scalar)1 / ((Scalar)2 * sqrtVal);
716
717 // vn = sqrt(v)
718 DScalar2 result(sqrtVal);
719
720 // Dvn = 1/(2 sqrt(v)) Dv
721 result.grad = s.grad * temp;
722
723 // D^2vn = 1/(2 sqrt(v)) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
724 result.hess = s.hess * temp;
725 result.hess += s.grad * s.grad.transpose()
726 * (-(Scalar)1 / ((Scalar)4 * s.value * sqrtVal));
727
728 return result;
729 }
730
731 friend DScalar2 pow(const DScalar2 &s, const Scalar &a)
732 {
733 Scalar powVal = std::pow(s.value, a),
734 temp = a * std::pow(s.value, a - 1);
735 // vn = v ^ a
736 DScalar2 result(powVal);
737
738 // Dvn = a*v^(a-1) * Dv
739 result.grad = s.grad * temp;
740
741 // D^2vn = a*v^(a-1) D^2v - 1/(4 v*sqrt(v)) Dv Dv^T
742 result.hess = s.hess * temp;
743 result.hess += s.grad * s.grad.transpose()
744 * (a * (a - 1) * std::pow(s.value, a - 2));
745
746 return result;
747 }
748
749 friend DScalar2 exp(const DScalar2 &s)
750 {
751 Scalar expVal = std::exp(s.value);
752
753 // vn = exp(v)
754 DScalar2 result(expVal);
755
756 // Dvn = exp(v) * Dv
757 result.grad = s.grad * expVal;
758
759 // D^2vn = exp(v) * Dv*Dv^T + exp(v) * D^2v
760 result.hess = (s.grad * s.grad.transpose()
761 + s.hess)
762 * expVal;
763
764 return result;
765 }
766
767 friend DScalar2 log(const DScalar2 &s)
768 {
769 Scalar logVal = std::log(s.value);
770
771 // vn = log(v)
772 DScalar2 result(logVal);
773
774 // Dvn = Dv / v
775 result.grad = s.grad / s.value;
776
777 // D^2vn = (v*D^2v - Dv*Dv^T)/(v^2)
778 result.hess = s.hess / s.value - (s.grad * s.grad.transpose() / (s.value * s.value));
779
780 return result;
781 }
782
783 friend DScalar2 sin(const DScalar2 &s)
784 {
785 Scalar sinVal = std::sin(s.value),
786 cosVal = std::cos(s.value);
787
788 // vn = sin(v)
789 DScalar2 result(sinVal);
790
791 // Dvn = cos(v) * Dv
792 result.grad = s.grad * cosVal;
793
794 // D^2vn = -sin(v) * Dv*Dv^T + cos(v) * Dv^2
795 result.hess = s.hess * cosVal;
796 result.hess += s.grad * s.grad.transpose() * -sinVal;
797
798 return result;
799 }
800
801 friend DScalar2 cos(const DScalar2 &s)
802 {
803 Scalar sinVal = std::sin(s.value),
804 cosVal = std::cos(s.value);
805 // vn = cos(v)
806 DScalar2 result(cosVal);
807
808 // Dvn = -sin(v) * Dv
809 result.grad = s.grad * -sinVal;
810
811 // D^2vn = -cos(v) * Dv*Dv^T - sin(v) * Dv^2
812 result.hess = s.hess * -sinVal;
813 result.hess += s.grad * s.grad.transpose() * -cosVal;
814
815 return result;
816 }
817
818 friend DScalar2 acos(const DScalar2 &s)
819 {
820 if (std::abs(s.value) >= 1)
821 throw std::runtime_error("acos: Expected a value in (-1, 1)");
822
823 Scalar temp = -std::sqrt((Scalar)1 - s.value * s.value);
824
825 // vn = acos(v)
826 DScalar2 result(std::acos(s.value));
827
828 // Dvn = -1/sqrt(1-v^2) * Dv
829 result.grad = s.grad * ((Scalar)1 / temp);
830
831 // D^2vn = -1/sqrt(1-v^2) * D^2v - v/[(1-v^2)^(3/2)] * Dv*Dv^T
832 result.hess = s.hess * ((Scalar)1 / temp);
833 result.hess += s.grad * s.grad.transpose()
834 * s.value / (temp * temp * temp);
835
836 return result;
837 }
838
839 friend DScalar2 asin(const DScalar2 &s)
840 {
841 if (std::abs(s.value) >= 1)
842 throw std::runtime_error("asin: Expected a value in (-1, 1)");
843
844 Scalar temp = std::sqrt((Scalar)1 - s.value * s.value);
845
846 // vn = asin(v)
847 DScalar2 result(std::asin(s.value));
848
849 // Dvn = 1/sqrt(1-v^2) * Dv
850 result.grad = s.grad * ((Scalar)1 / temp);
851
852 // D^2vn = 1/sqrt(1-v*v) * D^2v + v/[(1-v^2)^(3/2)] * Dv*Dv^T
853 result.hess = s.hess * ((Scalar)1 / temp);
854 result.hess += s.grad * s.grad.transpose()
855 * s.value / (temp * temp * temp);
856
857 return result;
858 }
859
860 friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x)
861 {
862 // vn = atan2(y, x)
863 DScalar2 result(std::atan2(y.value, x.value));
864
865 // Dvn = (x*Dy - y*Dx) / (x^2 + y^2)
866 Scalar denom = x.value * x.value + y.value * y.value,
867 denomSqr = denom * denom;
868 result.grad = y.grad * (x.value / denom)
869 - x.grad * (y.value / denom);
870
871 // D^2vn = (Dy*Dx^T + xD^2y - Dx*Dy^T - yD^2x) / (x^2+y^2)
872 // - [(x*Dy - y*Dx) * (2*x*Dx + 2*y*Dy)^T] / (x^2+y^2)^2
873 result.hess = (y.hess * x.value
874 + y.grad * x.grad.transpose()
875 - x.hess * y.value
876 - x.grad * y.grad.transpose())
877 / denom;
878
879 result.hess -=
880 (y.grad * (x.value / denomSqr) - x.grad * (y.value / denomSqr)) * (x.grad * ((Scalar)2 * x.value) + y.grad * ((Scalar)2 * y.value)).transpose();
881
882 return result;
883 }
884
886 // ======================================================================
887
888 // ======================================================================
890 // ======================================================================
891
892 inline void operator=(const DScalar2 &s)
893 {
894 value = s.value;
895 grad = s.grad;
896 hess = s.hess;
897 }
898 inline void operator=(const Scalar &v)
899 {
900 value = v;
901 grad.setZero();
902 hess.setZero();
903 }
904 inline bool operator<(const DScalar2 &s) const { return value < s.value; }
905 inline bool operator<=(const DScalar2 &s) const { return value <= s.value; }
906 inline bool operator>(const DScalar2 &s) const { return value > s.value; }
907 inline bool operator>=(const DScalar2 &s) const { return value >= s.value; }
908 inline bool operator<(const Scalar &s) const { return value < s; }
909 inline bool operator<=(const Scalar &s) const { return value <= s; }
910 inline bool operator>(const Scalar &s) const { return value > s; }
911 inline bool operator>=(const Scalar &s) const { return value >= s; }
912 inline bool operator==(const Scalar &s) const { return value == s; }
913 inline bool operator!=(const Scalar &s) const { return value != s; }
914
916 // ======================================================================
917
918 // ======================================================================
920 // ======================================================================
921
922#if defined(__MITSUBA_MITSUBA_H_) /* Mitsuba-specific */
924 static inline DVector2 vector(const mitsuba::TVector2<Scalar> &v)
925 {
926 return DVector2(DScalar2(v.x), DScalar2(v.y));
927 }
928
930 static inline DVector2 vector(const mitsuba::TPoint2<Scalar> &p)
931 {
932 return DVector2(DScalar2(p.x), DScalar2(p.y));
933 }
934
936 static inline DVector3 vector(const mitsuba::TVector3<Scalar> &v)
937 {
938 return DVector3(DScalar2(v.x), DScalar2(v.y), DScalar2(v.z));
939 }
940
942 static inline DVector3 vector(const mitsuba::TPoint3<Scalar> &p)
943 {
944 return DVector3(DScalar2(p.x), DScalar2(p.y), DScalar2(p.z));
945 }
946#endif
947
949 static inline DVector2 vector(const Eigen::Matrix<Scalar, 2, 1> &v)
950 {
951 return DVector2(DScalar2(v.x()), DScalar2(v.y()));
952 }
953
955 static inline DVector3 vector(const Eigen::Matrix<Scalar, 3, 1> &v)
956 {
957 return DVector3(DScalar2(v.x()), DScalar2(v.y()), DScalar2(v.z()));
958 }
959
961 // ======================================================================
962protected:
966};
967
968template <typename Scalar, typename VecType, typename MatType>
969std::ostream &operator<<(std::ostream &out, const DScalar2<Scalar, VecType, MatType> &s)
970{
971 out << "[" << s.getValue()
972 << ", grad=" << s.getGradient().format(Eigen::IOFormat(4, 1, ", ", "; ", "", "", "[", "]"))
973 << ", hess=" << s.getHessian().format(Eigen::IOFormat(4, 0, ", ", "; ", "", "", "[", "]"))
974 << "]";
975 return out;
976}
977
978#endif /* __AUTODIFF_H */
int y
int x
std::ostream & operator<<(std::ostream &out, const DScalar1< Scalar, VecType > &s)
Definition autodiff.h:459
Automatic differentiation scalar with first-order derivatives.
Definition autodiff.h:112
friend DScalar1 sin(const DScalar1 &s)
Definition autodiff.h:333
DScalar1(const DScalar1 &s)
Copy constructor.
Definition autodiff.h:146
DScalar1 & operator/=(const Scalar &v)
Definition autodiff.h:255
friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
Definition autodiff.h:369
friend DScalar1 operator-(const DScalar1 &s)
Definition autodiff.h:205
friend DScalar1 cos(const DScalar1 &s)
Definition autodiff.h:339
bool operator<=(const Scalar &s) const
Definition autodiff.h:400
DScalar1 & operator+=(const Scalar &v)
Definition autodiff.h:177
friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:268
DScalar1 & operator-=(const DScalar1 &s)
Definition autodiff.h:210
friend DScalar1 operator/(const DScalar1 &lhs, const DScalar1 &rhs)
Definition autodiff.h:241
bool operator==(const Scalar &s) const
Definition autodiff.h:403
_Scalar Scalar
Definition autodiff.h:114
friend DScalar1 operator*(const DScalar1 &lhs, const DScalar1 &rhs)
Definition autodiff.h:278
friend DScalar1 operator-(const DScalar1 &lhs, const DScalar1 &rhs)
Definition autodiff.h:190
const Gradient & getGradient() const
Definition autodiff.h:150
bool operator<(const DScalar1 &s) const
Definition autodiff.h:395
DScalar1 & operator+=(const DScalar1 &s)
Definition autodiff.h:170
bool operator>=(const Scalar &s) const
Definition autodiff.h:402
friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:195
bool operator>(const Scalar &s) const
Definition autodiff.h:401
bool operator!=(const Scalar &s) const
Definition autodiff.h:404
friend DScalar1 inverse(const DScalar1 &s)
Definition autodiff.h:246
friend DScalar1 operator/(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:228
friend DScalar1 operator/(const Scalar &lhs, const DScalar1 &rhs)
Definition autodiff.h:236
DScalar1(Scalar value_, const Gradient &grad_)
Construct a scalar associated with the given gradient.
Definition autodiff.h:142
friend DScalar1 operator*(const Scalar &lhs, const DScalar1 &rhs)
Definition autodiff.h:273
static DVector2 vector(const Eigen::Matrix< Scalar, 2, 1 > &v)
Initialize a constant two-dimensional vector.
Definition autodiff.h:414
DScalar1 & operator*=(const Scalar &v)
Definition autodiff.h:285
Eigen::Matrix< DScalar1, 2, 1 > DVector2
Definition autodiff.h:116
static DVector3 vector(const Eigen::Matrix< Scalar, 3, 1 > &v)
Create a constant three-dimensional vector.
Definition autodiff.h:420
bool operator>=(const DScalar1 &s) const
Definition autodiff.h:398
friend DScalar1 asin(const DScalar1 &s)
Definition autodiff.h:357
friend DScalar1 operator+(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:160
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:132
_Gradient Gradient
Definition autodiff.h:115
friend DScalar1 pow(const DScalar1 &s, const Scalar &a)
Definition autodiff.h:309
Scalar value
Definition autodiff.h:454
Gradient grad
Definition autodiff.h:455
bool operator<=(const DScalar1 &s) const
Definition autodiff.h:396
DScalar1(Scalar value_=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition autodiff.h:124
friend DScalar1 operator-(const Scalar &lhs, const DScalar1 &rhs)
Definition autodiff.h:200
DScalar1 & operator-=(const Scalar &v)
Definition autodiff.h:217
friend DScalar1 exp(const DScalar1 &s)
Definition autodiff.h:317
Eigen::Matrix< DScalar1, 3, 1 > DVector3
Definition autodiff.h:117
friend DScalar1 operator+(const Scalar &lhs, const DScalar1 &rhs)
Definition autodiff.h:165
friend DScalar1 operator+(const DScalar1 &lhs, const DScalar1 &rhs)
Definition autodiff.h:155
void operator=(const Scalar &v)
Definition autodiff.h:390
friend DScalar1 acos(const DScalar1 &s)
Definition autodiff.h:345
bool operator>(const DScalar1 &s) const
Definition autodiff.h:397
friend DScalar1 sqrt(const DScalar1 &s)
Definition autodiff.h:299
friend DScalar1 log(const DScalar1 &s)
Definition autodiff.h:325
const Scalar & getValue() const
Definition autodiff.h:149
bool operator<(const Scalar &s) const
Definition autodiff.h:399
void operator=(const DScalar1 &s)
Definition autodiff.h:385
Automatic differentiation scalar with first- and second-order derivatives.
Definition autodiff.h:493
Eigen::Matrix< DScalar2, 2, 1 > DVector2
Definition autodiff.h:498
bool operator<=(const Scalar &s) const
Definition autodiff.h:909
DScalar2 & operator+=(const DScalar2 &s)
Definition autodiff.h:560
Hessian hess
Definition autodiff.h:965
bool operator<(const Scalar &s) const
Definition autodiff.h:908
_Hessian Hessian
Definition autodiff.h:497
friend DScalar2 atan2(const DScalar2 &y, const DScalar2 &x)
Definition autodiff.h:860
friend DScalar2 sin(const DScalar2 &s)
Definition autodiff.h:783
bool operator>(const Scalar &s) const
Definition autodiff.h:910
bool operator>(const DScalar2 &s) const
Definition autodiff.h:906
const Scalar & getValue() const
Definition autodiff.h:537
friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:544
const Gradient & getGradient() const
Definition autodiff.h:538
bool operator<(const DScalar2 &s) const
Definition autodiff.h:904
friend DScalar2 inverse(const DScalar2 &s)
Definition autodiff.h:638
DScalar2 & operator/=(const Scalar &v)
Definition autodiff.h:658
friend DScalar2 operator*(const DScalar2 &lhs, const Scalar &rhs)
Definition autodiff.h:671
void operator=(const Scalar &v)
Definition autodiff.h:898
bool operator==(const Scalar &s) const
Definition autodiff.h:912
DScalar2 & operator+=(const Scalar &v)
Definition autodiff.h:568
friend DScalar2 cos(const DScalar2 &s)
Definition autodiff.h:801
friend DScalar2 acos(const DScalar2 &s)
Definition autodiff.h:818
DScalar2(Scalar value_, const Gradient &grad_, const Hessian &hess_)
Construct a scalar associated with the given gradient and Hessian.
Definition autodiff.h:530
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:517
bool operator>=(const Scalar &s) const
Definition autodiff.h:911
DScalar2(const DScalar2 &s)
Copy constructor.
Definition autodiff.h:534
bool operator>=(const DScalar2 &s) const
Definition autodiff.h:907
friend DScalar2 operator-(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:581
static DVector2 vector(const Eigen::Matrix< Scalar, 2, 1 > &v)
Initialize a constant two-dimensional vector.
Definition autodiff.h:949
const Hessian & getHessian() const
Definition autodiff.h:539
Eigen::Matrix< DScalar2, 3, 1 > DVector3
Definition autodiff.h:499
friend DScalar2 operator+(const DScalar2 &lhs, const Scalar &rhs)
Definition autodiff.h:550
friend DScalar2 exp(const DScalar2 &s)
Definition autodiff.h:749
friend DScalar2 log(const DScalar2 &s)
Definition autodiff.h:767
Scalar value
Definition autodiff.h:963
friend DScalar2 operator/(const DScalar2 &lhs, const Scalar &rhs)
Definition autodiff.h:620
DScalar2(Scalar value_=(Scalar) 0)
Create a new constant automatic differentiation scalar.
Definition autodiff.h:506
friend DScalar2 operator*(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:681
void operator=(const DScalar2 &s)
Definition autodiff.h:892
friend DScalar2 operator+(const Scalar &lhs, const DScalar2 &rhs)
Definition autodiff.h:555
bool operator<=(const DScalar2 &s) const
Definition autodiff.h:905
Gradient grad
Definition autodiff.h:964
_Gradient Gradient
Definition autodiff.h:496
friend DScalar2 operator/(const Scalar &lhs, const DScalar2 &rhs)
Definition autodiff.h:628
friend DScalar2 sqrt(const DScalar2 &s)
Definition autodiff.h:712
friend DScalar2 operator-(const DScalar2 &s)
Definition autodiff.h:596
friend DScalar2 asin(const DScalar2 &s)
Definition autodiff.h:839
DScalar2 & operator-=(const Scalar &v)
Definition autodiff.h:609
DScalar2 & operator-=(const DScalar2 &s)
Definition autodiff.h:601
friend DScalar2 pow(const DScalar2 &s, const Scalar &a)
Definition autodiff.h:731
friend DScalar2 operator*(const Scalar &lhs, const DScalar2 &rhs)
Definition autodiff.h:676
static DVector3 vector(const Eigen::Matrix< Scalar, 3, 1 > &v)
Create a constant three-dimensional vector.
Definition autodiff.h:955
DScalar2 & operator*=(const Scalar &v)
Definition autodiff.h:697
friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
Definition autodiff.h:591
bool operator!=(const Scalar &s) const
Definition autodiff.h:913
friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:633
_Scalar Scalar
Definition autodiff.h:495
friend DScalar2 operator-(const DScalar2 &lhs, const Scalar &rhs)
Definition autodiff.h:586
Base class of all automatic differentiation types.
Definition autodiff.h:41
static thread_local size_t m_variableCount
Definition autodiff.h:73
static size_t getVariableCount()
Get the variable count used by the automatic differentiation layer.
Definition autodiff.h:60
static void setVariableCount(size_t value)
Set the independent variable count used by the automatic differentiation layer.
Definition autodiff.h:54