Wildmeshing Toolkit
Loading...
Searching...
No Matches
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
113template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>>
115{
116public:
119 typedef Eigen::Matrix<DScalar1, 2, 1> DVector2;
120 typedef Eigen::Matrix<DScalar1, 3, 1> DVector3;
121
122 // ======================================================================
124 // ======================================================================
125
128 {
130 grad.resize(variableCount);
131 grad.setZero();
132 }
133
135 DScalar1(size_t index, const Scalar &value_)
136 : value(value_)
137 {
139 grad.resize(variableCount);
140 grad.setZero();
141 grad(index) = 1;
142 }
143
147
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
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
209 {
210 return DScalar1(-s.value, -s.grad);
211 }
212
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,
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 // ======================================================================
461protected:
464};
465
466template <typename Scalar, typename VecType>
467std::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
498template <typename _Scalar, typename _Gradient = Eigen::Matrix<_Scalar, Eigen::Dynamic, 1>,
499 typename _Hessian = Eigen::Matrix<_Scalar, Eigen::Dynamic, Eigen::Dynamic>>
501{
502public:
506 typedef Eigen::Matrix<DScalar2, 2, 1> DVector2;
507 typedef Eigen::Matrix<DScalar2, 3, 1> DVector3;
508
509 // ======================================================================
511 // ======================================================================
512
515 {
517
518 grad.resize(variableCount);
519 grad.setZero();
521 hess.setZero();
522 }
523
525 DScalar2(size_t index, const Scalar &value_)
526 : value(value_)
527 {
529
530 grad.resize(variableCount);
531 grad.setZero();
532 grad(index) = 1;
534 hess.setZero();
535 }
536
540
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
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
605 {
606 return DScalar2(-s.value, -s.grad, -s.hess);
607 }
608
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,
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)
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
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)
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)
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)
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)
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 // ======================================================================
977protected:
981};
982
983template <typename Scalar, typename VecType, typename MatType>
984std::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
995namespace std {
996
997template <typename _Scalar, typename _Gradient>
998class numeric_limits<DScalar1<_Scalar, _Gradient>>
999{
1000public:
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
1047template <typename _Scalar, typename _Gradient, typename _Hessian>
1048class numeric_limits<DScalar2<_Scalar, _Gradient, _Hessian>>
1049{
1050public:
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
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 Scalar &v)
Definition autodiff.h:258
friend DScalar1 atan2(const DScalar1 &y, const DScalar1 &x)
Definition autodiff.h:377
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:180
friend DScalar1 operator*(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:271
DScalar1 & operator-=(const DScalar1 &s)
Definition autodiff.h:213
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
const Gradient & getGradient() const
Definition autodiff.h:153
bool operator<(const DScalar1 &s) const
Definition autodiff.h:403
DScalar1 & operator+=(const DScalar1 &s)
Definition autodiff.h:173
bool operator>=(const Scalar &s) const
Definition autodiff.h:410
friend DScalar1 operator-(const DScalar1 &lhs, const Scalar &rhs)
Definition autodiff.h:198
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
DScalar1 & operator*=(const Scalar &v)
Definition autodiff.h:288
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(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
DScalar1 & operator-=(const Scalar &v)
Definition autodiff.h:220
friend DScalar1 abs(const DScalar1 &s)
Definition autodiff.h:302
friend DScalar1 exp(const DScalar1 &s)
Definition autodiff.h:325
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
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
friend DScalar1 log(const DScalar1 &s)
Definition autodiff.h:333
const Scalar & getValue() const
Definition autodiff.h:152
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
Eigen::Matrix< DScalar2, 2, 1 > DVector2
Definition autodiff.h:506
bool operator<=(const Scalar &s) const
Definition autodiff.h:924
DScalar2 & operator+=(const DScalar2 &s)
Definition autodiff.h:568
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
const Scalar & getValue() const
Definition autodiff.h:545
friend DScalar2 operator+(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:552
const Gradient & getGradient() const
Definition autodiff.h:546
bool operator<(const DScalar2 &s) const
Definition autodiff.h:917
friend DScalar2 inverse(const DScalar2 &s)
Definition autodiff.h:646
DScalar2 & operator/=(const Scalar &v)
Definition autodiff.h:666
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
DScalar2 & operator+=(const Scalar &v)
Definition autodiff.h:576
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
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
const Hessian & getHessian() const
Definition autodiff.h:547
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
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
friend DScalar2 asin(const DScalar2 &s)
Definition autodiff.h:852
DScalar2 & operator-=(const Scalar &v)
Definition autodiff.h:617
DScalar2 & operator-=(const DScalar2 &s)
Definition autodiff.h:609
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
DScalar2 & operator*=(const Scalar &v)
Definition autodiff.h:705
friend DScalar2 operator-(const Scalar &lhs, const DScalar2 &rhs)
Definition autodiff.h:599
bool operator!=(const Scalar &s) const
Definition autodiff.h:928
friend DScalar2 operator/(const DScalar2 &lhs, const DScalar2 &rhs)
Definition autodiff.h:641
_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