Fermat
diff.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * * Redistributions of source code must retain the above copyright
7  * notice, this list of conditions and the following disclaimer.
8  * * Redistributions in binary form must reproduce the above copyright
9  * notice, this list of conditions and the following disclaimer in the
10  * documentation and/or other materials provided with the distribution.
11  * * Neither the name of the NVIDIA CORPORATION nor the
12  * names of its contributors may be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
31 #pragma once
32 
33 #include <cugar/linalg/matrix.h>
34 #include <cugar/linalg/tensor.h>
35 #include <stdio.h>
36 
37 
38 namespace cugar {
39 
40  using ::expf;
41  using ::logf;
42  using ::sinf;
43  using ::cosf;
44  using ::sqrtf;
45 
46  using ::exp;
47  using ::log;
48  using ::sin;
49  using ::cos;
50  using ::sqrt;
51 
54 
58 
59 template <uint32 O1, uint32 O2>
60 struct static_min
61 {
62  static const uint32 value = O1 < O2 ? O1 : O2;
63 };
64 
78 template <typename ValType, uint32 N, uint32 O>
79 struct diff_var
80 {
81  typedef ValType value_type;
82  typedef diff_var<ValType,N,O-1> diff_component_type;
84 
85  value_type u;
86  diff_type du;
87 
90  CUGAR_HOST_DEVICE diff_var() : du(diff_component_type(value_type(0.0f))) {}
91 
94  CUGAR_HOST_DEVICE diff_var(const diff_var<ValType,N,O>& _other) : u(_other.u), du(_other.du) {}
95 
101  CUGAR_HOST_DEVICE diff_var(const value_type _u, const diff_type _du) : u(_u), du(_du) {}
102 
107  CUGAR_HOST_DEVICE explicit diff_var(value_type _u) : u(value_type(_u)), du(diff_component_type(0.0f)) {}
108 
111  CUGAR_HOST_DEVICE operator value_type() const { return u; }
112 
115  CUGAR_HOST_DEVICE diff_var& operator=(const value_type& _u) { u = _u; return *this; }
116 
119  CUGAR_HOST_DEVICE diff_type diff() const { return du; }
120 };
121 
131 template <typename ValType, uint32 N>
132 struct diff_var<ValType,N,0>
133 {
134  typedef ValType value_type;
135  typedef ValType diff_component_type;
137 
138  value_type u;
139 
142  CUGAR_HOST_DEVICE diff_var() {}
143 
146  CUGAR_HOST_DEVICE diff_var(const diff_var<ValType,N,0>& _other) : u(_other.u) {}
147 
152  CUGAR_HOST_DEVICE explicit diff_var(value_type _u) : u(_u) {}
153 
156  CUGAR_HOST_DEVICE operator value_type() const { return u; }
157 
160  CUGAR_HOST_DEVICE diff_var& operator=(const value_type& _u) { u = _u; return *this; }
161 
164  CUGAR_HOST_DEVICE diff_type diff() const { return diff_type(ValType(0.0f)); }
165 };
166 
175 template <typename ValType, uint32 O>
176 struct diff_var<ValType, 1, O>
177 {
178  typedef ValType value_type;
179  typedef diff_var<ValType,1,O-1> diff_component_type;
180  typedef diff_component_type diff_type;
181 
182  value_type u;
183  diff_type du;
184 
187  CUGAR_HOST_DEVICE diff_var() : du(diff_component_type(value_type(0.0f))) {}
188 
191  CUGAR_HOST_DEVICE diff_var(const diff_var<ValType,1,O>& _other) : u(_other.u), du(_other.du) {}
192 
198  CUGAR_HOST_DEVICE diff_var(const value_type _u, const diff_type _du) : u(_u), du(_du) {}
199 
205  CUGAR_HOST_DEVICE diff_var(const value_type _u, const value_type _du) : u(_u), du(diff_type(_du)) {}
206 
211  CUGAR_HOST_DEVICE explicit diff_var(value_type _u) : u(value_type(_u)), du(diff_component_type(value_type(0.0f))) {}
212 
215  CUGAR_HOST_DEVICE operator value_type() const { return u; }
216 
219  CUGAR_HOST_DEVICE diff_var& operator=(const value_type& _u) { u = _u; return *this; }
220 
223  CUGAR_HOST_DEVICE diff_type diff() const { return du; }
224 
225  // fake operator[] to pretend this is a 1-component vector
226  CUGAR_HOST_DEVICE const diff_var<ValType,1,O>& operator[] (const uint32 i) const { return *this; }
227  CUGAR_HOST_DEVICE diff_var<ValType,1,O>& operator[] (const uint32 i) { return *this; }
228 };
229 
238 template <typename ValType>
239 struct diff_var<ValType, 1, 0>
240 {
241  typedef ValType value_type;
242  typedef ValType diff_component_type;
243  typedef ValType diff_type;
244 
245  value_type u;
246 
249  CUGAR_HOST_DEVICE diff_var() {}
250 
253  CUGAR_HOST_DEVICE diff_var(const diff_var<ValType,1,0>& _other) : u(_other.u) {}
254 
259  CUGAR_HOST_DEVICE explicit diff_var(value_type _u) : u(_u) {}
260 
263  CUGAR_HOST_DEVICE operator value_type() const { return u; }
264 
267  CUGAR_HOST_DEVICE diff_var& operator=(const value_type& _u) { u = _u; return *this; }
268 
271  CUGAR_HOST_DEVICE diff_type diff() const { return diff_type(ValType(0.0f)); }
272 
273  // fake operator[] to pretend this is a 1-component vector
274  CUGAR_HOST_DEVICE const diff_var<ValType,1,0>& operator[] (const uint32 i) const { return *this; }
275  CUGAR_HOST_DEVICE diff_var<ValType,1,0>& operator[] (const uint32 i) { return *this; }
276 };
277 
281 template <typename VT, uint32 O>
282 CUGAR_HOST_DEVICE
283 inline void set_primary(diff_var<VT, 1, O>& var, const VT deriv = VT(1.0))
284 {
285  var.du = deriv;
286 }
287 
291 template <typename VT, uint32 N, uint32 O>
292 CUGAR_HOST_DEVICE
293 inline void set_primary(const uint32 i, diff_var<VT, N, O>& var, const VT deriv = VT(1.0))
294 {
295  var.du[i] = deriv;
296 }
297 
300 template <typename VT, uint32 N>
301 CUGAR_HOST_DEVICE
303 {
305  r.u = op.u;
306  return r;
307 }
308 
311 template <typename VT, uint32 N, uint32 O>
312 CUGAR_HOST_DEVICE
313 inline diff_var<VT, N, O-1> decrease_order(const diff_var<VT, N, O>& op)
314 {
315  diff_var<VT, N, O-1> r;
316  r.u = op.u;
317  for (uint32 i = 0; i < N; ++i)
318  r.du[i] = decrease_order(op.du[i]);
319  return r;
320 }
321 
324 template <typename VT, uint32 N>
325 CUGAR_HOST_DEVICE
327 {
329  r.u = op.u;
330  return r;
331 }
332 
335 template <typename VT, uint32 N, uint32 O>
336 CUGAR_HOST_DEVICE
338 {
340  r.u = op.u;
341  for (uint32 i = 0; i < N; ++i)
342  r.du[i] = raise_order(op.du[i]);
343  return r;
344 }
345 
348 template <typename VT, uint32 N, uint32 O>
349 CUGAR_HOST_DEVICE
351 {
353  for (uint32 i = 0; i < N; ++i)
354  r[i] = raise_order( op[i] );
355 
356  return r;
357 }
360 template <typename VT, uint32 N, uint32 O>
361 CUGAR_HOST_DEVICE
363 {
365  for (uint32 i = 0; i < N; ++i)
366  r[i] = raise_order( op[i] );
367 
368  return r;
369 }
372 template <typename VT, uint32 N, uint32 O, uint32 TO>
373 CUGAR_HOST_DEVICE
375 {
376  Tensor<diff_var<VT, N, O+1>, TO, N> r;
377  for (uint32 i = 0; i < N; ++i)
378  r[i] = raise_order( op[i] );
379 
380  return r;
381 }
382 
385 template <typename VT, uint32 N, uint32 O>
386 CUGAR_HOST_DEVICE
388 {
389  return op.diff();
390 }
391 
394 template <typename VT, uint32 N, uint32 O>
395 CUGAR_HOST_DEVICE
396 inline Tensor<diff_var<VT, N, O-2>, 2, N> diff_hessian(const diff_var<VT, N, O> op)
397 {
398  Tensor<diff_var<VT, N, O-2>, 2, N> H;
399  for (uint32 i = 0; i < N; ++i)
400  for (uint32 j = 0; j < N; ++j)
401  H(i,j) = diff( diff(op)[i] )[j];
402 
403  return H;
404 }
405 
408 template <typename VT, uint32 N, uint32 O>
409 CUGAR_HOST_DEVICE
411 {
413  for (uint32 i = 0; i < N; ++i)
414  J[i] = diff(op)[i];
415 
416  return J;
417 }
418 
421 template <typename VT, uint32 N, uint32 O>
422 CUGAR_HOST_DEVICE
424 {
426  for (uint32 i = 0; i < N; ++i)
427  J[i] = diff(op)[i];
428 
429  return J;
430 }
431 
434 template <typename VT, uint32 N, uint32 O>
435 CUGAR_HOST_DEVICE
437 {
439  for (uint32 i = 0; i < N; ++i)
440  for (uint32 j = 0; j < N; ++j)
441  H(i,j) = diff( diff(op)[i] )[j];
442 
443  return H;
444 }
445 
446 namespace detail {
447 
448 template <uint32 ORDER> struct dispatch_diff_tensor {};
449 
450 template <>
452 {
453  template <typename VT, uint32 N, uint32 O>
454  CUGAR_HOST_DEVICE
455  static inline Tensor<VT, 1, N> apply(const diff_var<VT, N, O> op)
456  {
458  for (uint32 i = 0; i < N; ++i)
459  for (uint32 j = 0; j < N; ++j)
460  T(i) = diff(op)[i];
461 
462  return T;
463  }
464 };
465 
466 template <>
468 {
469  template <typename VT, uint32 N, uint32 O>
470  CUGAR_HOST_DEVICE
471  static inline Tensor<VT, 2, N> apply(const diff_var<VT, N, O> op)
472  {
474  for (uint32 i = 0; i < N; ++i)
475  for (uint32 j = 0; j < N; ++j)
476  T(i,j) = diff( diff(op)[i] )[j];
477 
478  return T;
479  }
480 };
481 
482 template <>
484 {
485  template <typename VT, uint32 N, uint32 O>
486  CUGAR_HOST_DEVICE
487  static inline Tensor<VT, 3, N> apply(const diff_var<VT, N, O> op)
488  {
490  for (uint32 i = 0; i < N; ++i)
491  for (uint32 j = 0; j < N; ++j)
492  for (uint32 k = 0; k < N; ++k)
493  T(i,j,k) = diff( diff( diff(op)[i] )[j] )[k];
494 
495  return T;
496  }
497 };
498 
499 } // namespace detail
500 
505 template <uint32 ORDER, typename VT, uint32 N, uint32 O>
506 CUGAR_HOST_DEVICE
508 {
510 }
511 
512 // special-case negation for zero-order vars
513 template <typename VT, uint32 N>
514 CUGAR_HOST_DEVICE
515 inline diff_var<VT,N,0> operator-(const diff_var<VT,N,0> a)
516 {
517  return diff_var<VT,N,0>( -a.u );
518 }
519 
520 // special-case subtraction for zero-order vars
521 template <typename VT, uint32 N>
522 CUGAR_HOST_DEVICE
523 inline diff_var<VT,N,0> operator-(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
524 {
525  return diff_var<VT,N,0>( a.u - b.u );
526 }
527 
528 // special-case subtraction for zero-order vars
529 template <typename VT, uint32 N>
530 CUGAR_HOST_DEVICE
531 inline diff_var<VT,N,0> operator-(const diff_var<VT,N,0> a, const VT b)
532 {
533  return diff_var<VT,N,0>( a.u - b );
534 }
535 
536 // special-case subtraction for zero-order vars
537 template <typename VT, uint32 N>
538 CUGAR_HOST_DEVICE
539 inline diff_var<VT,N,0> operator-(const VT a, const diff_var<VT,N,0> b)
540 {
541  return diff_var<VT,N,0>( a - b.u );
542 }
543 
544 
545 // addition of zero-order vars
546 template <typename VT, uint32 N>
547 CUGAR_HOST_DEVICE
548 inline diff_var<VT,N,0> operator+(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
549 {
550  return diff_var<VT,N,0>( a.u + b.u );
551 }
552 
553 // addition of zero-order var with scalar
554 template <typename VT, uint32 N>
555 CUGAR_HOST_DEVICE
556 inline diff_var<VT,N,0> operator+(const diff_var<VT,N,0> a, const VT b)
557 {
558  return diff_var<VT,N,0>( a.u + b );
559 }
560 
561 // addition of zero-order var with scalar
562 template <typename VT, uint32 N>
563 CUGAR_HOST_DEVICE
564 inline diff_var<VT,N,0> operator+(const VT a, const diff_var<VT,N,0> b)
565 {
566  return diff_var<VT,N,0>( a + b.u );
567 }
568 
569 // multiplication of zero-order var by scalar
570 template <typename VT, uint32 N>
571 CUGAR_HOST_DEVICE
572 inline diff_var<VT,N,0> operator*(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
573 {
574  return diff_var<VT,N,0>( a.u * b.u );
575 }
576 
577 // multiplication of zero-order var by scalar
578 template <typename VT, uint32 N>
579 CUGAR_HOST_DEVICE
580 inline diff_var<VT,N,0> operator*(const diff_var<VT,N,0> a, const VT b)
581 {
582  return diff_var<VT,N,0>( a.u * b );
583 }
584 
585 // multiplication of zero-order vars
586 template <typename VT, uint32 N>
587 CUGAR_HOST_DEVICE
588 inline diff_var<VT,N,0> operator*(const VT a, const diff_var<VT,N,0> b)
589 {
590  return diff_var<VT,N,0>( a * b.u );
591 }
592 
593 // division of zero-order vars
594 template <typename VT, uint32 N>
595 CUGAR_HOST_DEVICE
596 inline diff_var<VT,N,0> operator/(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
597 {
598  return diff_var<VT,N,0>( a.u / b.u );
599 }
600 
601 // division of a zero-order var by scalar
602 template <typename VT, uint32 N>
603 CUGAR_HOST_DEVICE
604 inline diff_var<VT,N,0> operator/(const diff_var<VT,N,0> a, const VT b)
605 {
606  return diff_var<VT,N,0>( a.u / b );
607 }
608 
609 namespace detail {
610 
611 // addition of arbitrary order vars
612 template <typename VT, uint32 N, uint32 O1, uint32 O2>
614 {
615  static const uint32 RO = static_min<O1,O2>::value;
616 
617  // fully general case
618  CUGAR_HOST_DEVICE
619  static inline diff_var<VT,N,RO> apply(const diff_var<VT,N,O1> a, const diff_var<VT,N,O2> b)
620  {
622 
623  r.u = a.u + b.u;
624 
625  // component-wise expression
626  for (uint32 i = 0; i < N; ++i)
627  r.du[i] = a.du[i] + b.du[i];
628 
629  return r;
630  }
631 };
632 
633 // addition of zero-order vars
634 template <typename VT, uint32 N>
635 struct dispatch_sum<VT,N,0,0>
636 {
637  static const uint32 RO = 0;
638 
639  CUGAR_HOST_DEVICE
640  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
641  {
642  return diff_var<VT,N,0>( a.u + b.u );
643  }
644 };
645 
646 // right-addition with a zero-order var
647 template <typename VT, uint32 N, uint32 O>
648 struct dispatch_sum<VT,N,O,0>
649 {
650  static const uint32 RO = 0;
651 
652  CUGAR_HOST_DEVICE
653  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,O> a, const diff_var<VT,N,0> b)
654  {
655  return diff_var<VT,N,0>( a.u + b.u );
656  }
657 };
658 
659 // left-addition with a zero-order var
660 template <typename VT, uint32 N, uint32 O>
661 struct dispatch_sum<VT,N,0,O>
662 {
663  static const uint32 RO = 0;
664 
665  CUGAR_HOST_DEVICE
666  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,O> b)
667  {
668  return diff_var<VT,N,0>( a.u + b.u );
669  }
670 };
671 
672 // multiplication of arbitrary order vars
673 template <typename VT, uint32 N, uint32 O1, uint32 O2>
675 {
676  static const uint32 RO = static_min<O1,O2>::value;
677 
678  // fully general case
679  CUGAR_HOST_DEVICE
680  static inline diff_var<VT,N,RO> apply(const diff_var<VT,N,O1> a, const diff_var<VT,N,O2> b)
681  {
683 
684  r.u = a.u * b.u;
685 
686  // component-wise expression
687  for (uint32 i = 0; i < N; ++i)
688  r.du[i] = a.du[i] * b + a * b.du[i];
689 
690  return r;
691  }
692 };
693 
694 // addition of zero-order vars
695 template <typename VT, uint32 N>
696 struct dispatch_mul<VT,N,0,0>
697 {
698  static const uint32 RO = 0;
699 
700  CUGAR_HOST_DEVICE
701  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
702  {
703  return diff_var<VT,N,0>( a.u * b.u );
704  }
705 };
706 
707 // right-addition with a zero-order var
708 template <typename VT, uint32 N, uint32 O>
709 struct dispatch_mul<VT,N,O,0>
710 {
711  static const uint32 RO = 0;
712 
713  CUGAR_HOST_DEVICE
714  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,O> a, const diff_var<VT,N,0> b)
715  {
716  return diff_var<VT,N,0>( a.u * b.u );
717  }
718 };
719 
720 // left-addition with a zero-order var
721 template <typename VT, uint32 N, uint32 O>
722 struct dispatch_mul<VT,N,0,O>
723 {
724  static const uint32 RO = 0;
725 
726  CUGAR_HOST_DEVICE
727  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,O> b)
728  {
729  return diff_var<VT,N,0>( a.u * b.u );
730  }
731 };
732 
733 
734 // division of arbitrary order vars
735 template <typename VT, uint32 N, uint32 O1, uint32 O2>
737 {
738  static const uint32 RO = static_min<O1,O2>::value;
739 
740  // fully general case
741  CUGAR_HOST_DEVICE
742  static inline diff_var<VT,N,RO> apply(const diff_var<VT,N,O1> a, const diff_var<VT,N,O2> b)
743  {
745 
746  r.u = a.u / b.u;
747 
748  // component-wise expression
749  for (uint32 i = 0; i < N; ++i)
750  r.du[i] = (a.du[i] * b - a * b.du[i]) / (b * b);
751 
752  return r;
753  }
754 };
755 
756 // division of zero-order vars
757 template <typename VT, uint32 N>
758 struct dispatch_div<VT,N,0,0>
759 {
760  static const uint32 RO = 0;
761 
762  CUGAR_HOST_DEVICE
763  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,0> b)
764  {
765  return diff_var<VT,N,0>( a.u / b.u );
766  }
767 };
768 
769 // right-division with a zero-order var
770 template <typename VT, uint32 N, uint32 O>
771 struct dispatch_div<VT,N,O,0>
772 {
773  static const uint32 RO = 0;
774 
775  CUGAR_HOST_DEVICE
776  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,O> a, const diff_var<VT,N,0> b)
777  {
778  return diff_var<VT,N,0>( a.u / b.u );
779  }
780 };
781 
782 // left-division with a zero-order var
783 template <typename VT, uint32 N, uint32 O>
784 struct dispatch_div<VT,N,0,O>
785 {
786  static const uint32 RO = 0;
787 
788  CUGAR_HOST_DEVICE
789  static inline diff_var<VT,N,0> apply(const diff_var<VT,N,0> a, const diff_var<VT,N,O> b)
790  {
791  return diff_var<VT,N,0>( a.u / b.u );
792  }
793 };
794 
795 } // namespace detail
796 
799 template <typename VT, uint32 N, uint32 O1, uint32 O2>
800 CUGAR_HOST_DEVICE
802 {
804 }
805 
808 template <typename VT, uint32 N, uint32 O>
809 CUGAR_HOST_DEVICE
810 inline diff_var<VT,N,O> operator+(const diff_var<VT,N,O> a, const VT b)
811 {
812  return diff_var<VT,N,O>( a.u + b, a.du );
813 }
814 
817 template <typename VT, uint32 N, uint32 O>
818 CUGAR_HOST_DEVICE
819 inline diff_var<VT,N,O> operator+(const VT a, const diff_var<VT,N,O> b)
820 {
821  return diff_var<VT,N,O>( a + b.du, b.du );
822 }
823 
826 template <typename VT, uint32 N, uint32 O>
827 CUGAR_HOST_DEVICE
828 inline diff_var<VT,N,O> operator-(const diff_var<VT,N,O> a)
829 {
830  return diff_var<VT,N,O>( -a.u, -a.du );
831 }
832 
835 template <typename VT, uint32 N, uint32 O>
836 CUGAR_HOST_DEVICE
837 inline diff_var<VT,N,O> operator-(const diff_var<VT,N,O> a, const VT b)
838 {
839  return diff_var<VT,N,O>( a.u - b, a.du );
840 }
841 
844 template <typename VT, uint32 N, uint32 O>
845 CUGAR_HOST_DEVICE
846 inline diff_var<VT,N,O> operator-(const VT a, const diff_var<VT,N,O> b)
847 {
848  return diff_var<VT,N,O>( a - b.u, -b.du );
849 }
850 
853 template <typename VT, uint32 N, uint32 O1, uint32 O2>
854 CUGAR_HOST_DEVICE
856 {
858 }
859 
862 template <typename VT, uint32 N, uint32 O1, uint32 O2>
863 CUGAR_HOST_DEVICE
865 {
867 }
868 
871 template <typename VT, uint32 N, uint32 O>
872 CUGAR_HOST_DEVICE
873 inline diff_var<VT,N,O> operator*(const diff_var<VT,N,O> a, const VT b)
874 {
876  r.u = a.u * b;
877 
878  // component-wise expression
879  for (uint32 i = 0; i < N; ++i)
880  r.du[i] = a.du[i] * b;
881 
882  return r;
883 }
886 template <typename VT, uint32 N, uint32 O>
887 CUGAR_HOST_DEVICE
888 inline diff_var<VT,N,O> operator*(const VT a, const diff_var<VT,N,O> b)
889 {
891  r.u = a * b.u;
892 
893  // component-wise expression
894  for (uint32 i = 0; i < N; ++i)
895  r.du[i] = a * b.du[i];
896 
897  return r;
898 }
899 
902 template <typename VT, uint32 N, uint32 O1, uint32 O2>
903 CUGAR_HOST_DEVICE
905 {
907 }
908 
911 template <typename VT, uint32 N, uint32 O>
912 CUGAR_HOST_DEVICE
913 inline diff_var<VT,N,O> operator/(const diff_var<VT,N,O> a, const VT b)
914 {
915  return diff_var<VT,N,O>( a.u / b, a.du / b );
916 }
917 
920 template <typename VT, uint32 N, uint32 O>
921 CUGAR_HOST_DEVICE
922 inline diff_var<VT,N,O> operator/(const VT a, const diff_var<VT,N,O> b)
923 {
925 }
926 
929 template <typename VT, uint32 N, uint32 O>
930 CUGAR_HOST_DEVICE
932 {
933  a = a + b;
934  return a;
935 }
938 template <typename VT, uint32 N, uint32 O>
939 CUGAR_HOST_DEVICE
941 {
942  a = a - b;
943  return a;
944 }
947 template <typename VT, uint32 N, uint32 O>
948 CUGAR_HOST_DEVICE
950 {
951  a = a * b;
952  return a;
953 }
956 template <typename VT, uint32 N, uint32 O>
957 CUGAR_HOST_DEVICE
959 {
960  a = a / b;
961  return a;
962 }
963 
964 
965 // zero-order specialization of sin
966 template <uint32 N>
967 CUGAR_HOST_DEVICE
968 inline diff_var<float,N,0> sin(const diff_var<float,N,0> a)
969 {
970  return diff_var<float,N,0>( ::sinf(a.u) );
971 }
972 // zero-order specialization of cos
973 template <uint32 N>
974 CUGAR_HOST_DEVICE
975 inline diff_var<float,N,0> cos(const diff_var<float,N,0> a)
976 {
977  return diff_var<float,N,0>( ::cosf(a.u) );
978 }
979 // zero-order specialization of log
980 template <uint32 N>
981 CUGAR_HOST_DEVICE
982 inline diff_var<float,N,0> log(const diff_var<float,N,0> a)
983 {
984  return diff_var<float,N,0>( ::logf(a.u) );
985 }
986 // zero-order specialization of exp
987 template <uint32 N>
988 CUGAR_HOST_DEVICE
989 inline diff_var<float,N,0> exp(const diff_var<float,N,0> a)
990 {
991  return diff_var<float,N,0>( ::expf(a.u) );
992 }
993 // zero-order specialization of sqrt
994 template <uint32 N>
995 CUGAR_HOST_DEVICE
996 inline diff_var<float,N,0> sqrt(const diff_var<float,N,0> a)
997 {
998  return diff_var<float,N,0>( ::sqrtf(a.u) );
999 }
1000 
1001 // arbitrary-order specialization of sin
1002 template <uint32 N, uint32 O>
1003 CUGAR_HOST_DEVICE
1004 inline diff_var<float,N,O> sin(const diff_var<float,N,O> a)
1005 {
1007  r.u = ::sinf(a.u);
1008 
1009  // component-wise expression
1010  for (uint32 i = 0; i < N; ++i)
1011  r.du[i] = cos( decrease_order( a ) ) * a.du[i];
1012 
1013  return r;
1014 }
1015 // arbitrary-order specialization of cos
1016 template <uint32 N, uint32 O>
1017 CUGAR_HOST_DEVICE
1018 inline diff_var<float,N,O> cos(const diff_var<float,N,O> a)
1019 {
1021  r.u = ::cosf(a.u);
1022 
1023  // component-wise expression
1024  for (uint32 i = 0; i < N; ++i)
1025  r.du[i] = -sin( decrease_order( a ) ) * a.du[i];
1026 
1027  return r;
1028 }
1029 
1030 // arbitrary-order specialization of log
1031 template <uint32 N, uint32 O>
1032 CUGAR_HOST_DEVICE
1033 inline diff_var<float,N,O> log(const diff_var<float,N,O> a)
1034 {
1036  r.u = ::logf(a.u);
1037 
1038  // component-wise expression
1039  for (uint32 i = 0; i < N; ++i)
1040  r.du[i] = a.du[i] / a;
1041 
1042  return r;
1043 }
1044 
1045 // arbitrary-order specialization of exp
1046 template <uint32 N, uint32 O>
1047 CUGAR_HOST_DEVICE
1048 inline diff_var<float,N,O> exp(const diff_var<float,N,O> a)
1049 {
1051  r.u = ::expf(a.u);
1052 
1053  // component-wise expression
1054  for (uint32 i = 0; i < N; ++i)
1055  r.du[i] = exp( decrease_order( a ) ) * a.du[i];
1056 
1057  return r;
1058 }
1059 
1060 // arbitrary-order specialization of sqrt
1061 template <uint32 N, uint32 O>
1062 CUGAR_HOST_DEVICE
1063 inline diff_var<float,N,O> sqrt(const diff_var<float,N,O> a)
1064 {
1066  r.u = ::sqrtf(a.u);
1067 
1068  // component-wise expression
1069  for (uint32 i = 0; i < N; ++i)
1070  r.du[i] = a.du[i] * 0.5f / sqrt(decrease_order(a));
1071 
1072  return r;
1073 }
1074 
1075 template <uint32 N, uint32 O>
1076 CUGAR_HOST_DEVICE
1077 inline diff_var<float,N,O> sinf(const diff_var<float,N,O> a) { return sin(a); }
1078 
1079 template <uint32 N, uint32 O>
1080 CUGAR_HOST_DEVICE
1081 inline diff_var<float,N,O> cosf(const diff_var<float,N,O> a) { return cos(a); }
1082 
1083 template <uint32 N, uint32 O>
1084 CUGAR_HOST_DEVICE
1085 inline diff_var<float,N,O> logf(const diff_var<float,N,O> a) { return log(a); }
1086 
1087 template <uint32 N, uint32 O>
1088 CUGAR_HOST_DEVICE
1089 inline diff_var<float,N,O> expf(const diff_var<float,N,O> a) { return exp(a); }
1090 
1091 template <uint32 N, uint32 O>
1092 CUGAR_HOST_DEVICE
1093 inline diff_var<float,N,O> sqrtf(const diff_var<float,N,O> a) { return sqrt(a); }
1094 
1095 // zero-order specialization of sin
1096 template <typename VT, uint32 N>
1097 CUGAR_HOST_DEVICE
1098 inline diff_var<VT,N,0> sin(const diff_var<VT,N,0> a)
1099 {
1100  return diff_var<VT,N,0>( sin(a.u) );
1101 }
1102 // zero-order specialization of cos
1103 template <typename VT, uint32 N>
1104 CUGAR_HOST_DEVICE
1105 inline diff_var<VT,N,0> cos(const diff_var<VT,N,0> a)
1106 {
1107  return diff_var<VT,N,0>( cos(a.u) );
1108 }
1109 // zero-order specialization of log
1110 template <typename VT, uint32 N>
1111 CUGAR_HOST_DEVICE
1112 inline diff_var<VT,N,0> log(const diff_var<VT,N,0> a)
1113 {
1114  return diff_var<VT,N,0>( log(a.u) );
1115 }
1116 // zero-order specialization of exp
1117 template <typename VT, uint32 N>
1118 CUGAR_HOST_DEVICE
1119 inline diff_var<VT,N,0> exp(const diff_var<VT,N,0> a)
1120 {
1121  return diff_var<float,N,0>( exp(a.u) );
1122 }
1123 // zero-order specialization of sqrt
1124 template <typename VT, uint32 N>
1125 CUGAR_HOST_DEVICE
1126 inline diff_var<VT,N,0> sqrt(const diff_var<VT,N,0> a)
1127 {
1128  return diff_var<VT,N,0>( sqrt(a.u) );
1129 }
1130 
1131 // arbitrary-order specialization of sin
1132 template <typename VT, uint32 N, uint32 O>
1133 CUGAR_HOST_DEVICE
1134 inline diff_var<VT,N,O> sin(const diff_var<VT,N,O> a)
1135 {
1136  diff_var<VT,N,O> r;
1137  r.u = sin(a.u);
1138 
1139  // component-wise expression
1140  for (uint32 i = 0; i < N; ++i)
1141  r.du[i] = cos( decrease_order( a ) ) * a.du[i];
1142 
1143  return r;
1144 }
1145 // arbitrary-order specialization of cos
1146 template <typename VT, uint32 N, uint32 O>
1147 CUGAR_HOST_DEVICE
1148 inline diff_var<VT,N,O> cos(const diff_var<VT,N,O> a)
1149 {
1150  diff_var<VT,N,O> r;
1151  r.u = cos(a.u);
1152 
1153  // component-wise expression
1154  for (uint32 i = 0; i < N; ++i)
1155  r.du[i] = -sin( decrease_order( a ) ) * a.du[i];
1156 
1157  return r;
1158 }
1159 
1160 // arbitrary-order specialization of log
1161 template <typename VT, uint32 N, uint32 O>
1162 CUGAR_HOST_DEVICE
1163 inline diff_var<VT,N,O> log(const diff_var<VT,N,O> a)
1164 {
1165  diff_var<VT,N,O> r;
1166  r.u = log(a.u);
1167 
1168  // component-wise expression
1169  for (uint32 i = 0; i < N; ++i)
1170  r.du[i] = a.du[i] / a;
1171 
1172  return r;
1173 }
1174 
1175 // arbitrary-order specialization of exp
1176 template <typename VT, uint32 N, uint32 O>
1177 CUGAR_HOST_DEVICE
1178 inline diff_var<VT,N,O> exp(const diff_var<VT,N,O> a)
1179 {
1180  diff_var<VT,N,O> r;
1181  r.u = exp(a.u);
1182 
1183  // component-wise expression
1184  for (uint32 i = 0; i < N; ++i)
1185  r.du[i] = exp( decrease_order( a ) ) * a.du[i];
1186 
1187  return r;
1188 }
1189 
1190 // arbitrary-order specialization of sqrt
1191 template <typename VT, uint32 N, uint32 O>
1192 CUGAR_HOST_DEVICE
1193 inline diff_var<VT,N,O> sqrt(const diff_var<VT,N,O> a)
1194 {
1195  diff_var<VT,N,O> r;
1196  r.u = sqrt(a.u);
1197 
1198  // component-wise expression
1199  for (uint32 i = 0; i < N; ++i)
1200  r.du[i] = (a.du[i] * VT(0.5f)) / sqrt(decrease_order(a));
1201 
1202  return r;
1203 }
1204 
1205 template <typename VT, uint32 N, uint32 O>
1206 CUGAR_HOST_DEVICE
1207 inline diff_var<VT,N,O> max(const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u > b.u ? a : b; }
1208 
1209 template <typename VT, uint32 N, uint32 O>
1210 CUGAR_HOST_DEVICE
1211 inline diff_var<VT,N,O> min(const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u < b.u ? a : b; }
1212 
1213 template <typename VT, uint32 N, uint32 O>
1214 CUGAR_HOST_DEVICE
1215 inline bool operator< (const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u < b.u; }
1216 
1217 template <typename VT, uint32 N, uint32 O>
1218 CUGAR_HOST_DEVICE
1219 inline bool operator<= (const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u <= b.u; }
1220 
1221 template <typename VT, uint32 N, uint32 O>
1222 CUGAR_HOST_DEVICE
1223 inline bool operator> (const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u > b.u; }
1224 
1225 template <typename VT, uint32 N, uint32 O>
1226 CUGAR_HOST_DEVICE
1227 inline bool operator>= (const diff_var<VT,N,O> a, const diff_var<VT,N,O> b) { return a.u >= b.u; }
1228 
1231 
1232 } // namespace cugar
CUGAR_HOST_DEVICE Tensor< VT, 2, N > hessian(const diff_var< VT, N, O > op)
Definition: diff.h:436
CUGAR_HOST_DEVICE Tensor< VT, 1, N > jacobian(const diff_var< VT, N, O > op)
Definition: diff.h:423
CUGAR_HOST_DEVICE diff_var< VT, N, O > & operator+=(diff_var< VT, N, O > &a, const diff_var< VT, N, O > b)
Definition: diff.h:931
CUGAR_HOST_DEVICE diff_type diff() const
Definition: diff.h:271
CUGAR_HOST_DEVICE diff_var(value_type _u)
Definition: diff.h:211
CUGAR_HOST_DEVICE diff_var(value_type _u)
Definition: diff.h:259
Definition: diff.h:60
CUGAR_HOST_DEVICE diff_type diff() const
Definition: diff.h:119
CUGAR_HOST_DEVICE diff_var< VT, N, 1 > raise_order(const diff_var< VT, N, 0 > &op)
Definition: diff.h:326
CUGAR_HOST_DEVICE diff_type diff() const
Definition: diff.h:164
CUGAR_HOST_DEVICE diff_var(const value_type _u, const diff_type _du)
Definition: diff.h:101
CUGAR_HOST_DEVICE diff_var & operator=(const value_type &_u)
Definition: diff.h:160
CUGAR_HOST_DEVICE diff_var(value_type _u)
Definition: diff.h:152
Definition: diff.h:613
CUGAR_HOST_DEVICE diff_var(const value_type _u, const value_type _du)
Definition: diff.h:205
Definition: diff.h:176
CUGAR_HOST_DEVICE diff_var(const diff_var< ValType, 1, 0 > &_other)
Definition: diff.h:253
Definition: diff.h:674
CUGAR_HOST_DEVICE diff_var(const diff_var< ValType, N, O > &_other)
Definition: diff.h:94
CUGAR_HOST_DEVICE diff_var< VT, N, O > & operator*=(diff_var< VT, N, O > &a, const diff_var< VT, N, O > b)
Definition: diff.h:949
CUGAR_HOST_DEVICE diff_var< VT, N, 0 > decrease_order(const diff_var< VT, N, 1 > &op)
Definition: diff.h:302
CUGAR_HOST_DEVICE diff_var(const diff_var< ValType, 1, O > &_other)
Definition: diff.h:191
CUGAR_HOST_DEVICE diff_var(const value_type _u, const diff_type _du)
Definition: diff.h:198
CUGAR_HOST_DEVICE diff_var & operator=(const value_type &_u)
Definition: diff.h:115
Definition: diff.h:239
CUGAR_HOST_DEVICE diff_var()
Definition: diff.h:249
CUGAR_HOST_DEVICE diff_var()
Definition: diff.h:90
CUGAR_HOST_DEVICE Tensor< diff_var< VT, N, O-2 >, 2, N > diff_hessian(const diff_var< VT, N, O > op)
Definition: diff.h:396
CUGAR_HOST_DEVICE diff_type diff() const
Definition: diff.h:223
CUGAR_HOST_DEVICE diff_var & operator=(const value_type &_u)
Definition: diff.h:219
CUGAR_HOST_DEVICE diff_var & operator=(const value_type &_u)
Definition: diff.h:267
CUGAR_HOST_DEVICE Tensor< VT, 1, N > gradient(const diff_var< VT, N, O > op)
Definition: diff.h:410
Definition: diff.h:132
CUGAR_HOST_DEVICE diff_var()
Definition: diff.h:187
Define a vector_view POD type and plain_view() for std::vector.
Definition: diff.h:38
CUGAR_HOST_DEVICE diff_var()
Definition: diff.h:142
CUGAR_HOST_DEVICE diff_var< VT, N, O > & operator/=(diff_var< VT, N, O > &a, const diff_var< VT, N, O > b)
Definition: diff.h:958
CUGAR_HOST_DEVICE diff_var(value_type _u)
Definition: diff.h:107
CUGAR_HOST_DEVICE diff_var(const diff_var< ValType, N, 0 > &_other)
Definition: diff.h:146
CUGAR_HOST_DEVICE Tensor< VT, ORDER, N > diff_tensor(const diff_var< VT, N, O > op)
Definition: diff.h:507
CUGAR_HOST_DEVICE void set_primary(diff_var< VT, 1, O > &var, const VT deriv=VT(1.0))
Definition: diff.h:283
Definition: diff.h:736
Definition: diff.h:79
CUGAR_HOST_DEVICE diff_var< VT, N, O > & operator-=(diff_var< VT, N, O > &a, const diff_var< VT, N, O > b)
Definition: diff.h:940
CUGAR_HOST_DEVICE diff_var< VT, N, O >::diff_type diff(const diff_var< VT, N, O > op)
Definition: diff.h:387
Definition: tensor.h:43