29 #ifndef __ADOperators_H
30 #define __ADOperators_H 1
41 template <
class L,
class R>
45 enum { nvar = L::nvar };
46 typedef typename L::value_type value_type_L;
48 typedef typename R::value_type value_type_R;
50 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type;
59 ADBinaryAdd(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
69 value_type value()
const
71 return __left.value() + __right.value();
73 value_type grad(
int __i )
const
75 return __left.grad( __i ) + __right.grad( __i );
77 value_type
hessian(
int __i,
int __j )
const
79 return __left.hessian( __i, __j ) + __right.hessian( __i, __j );
83 bool deps(
int i )
const
85 return __left.deps( i ) || __right.deps( i );
89 #define AD_BIN_ADD_CST(TYPE) \
91 class ADBinaryAdd<L, ADCst<TYPE> > \
94 enum { nvar = L::nvar }; \
96 typedef typename L::value_type value_type_L; \
97 typedef TYPE value_type_R; \
98 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
99 typedef ADCst<TYPE> R; \
104 const L& __left; const R __right; \
107 ADBinaryAdd(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
111 value_type value() const {return __left.value() + __right.value();} \
112 value_type grad( int __i ) const {return __left.grad( __i );} \
113 value_type hessian( int __i, int __j ) const {return __left.hessian(__i, __j);} \
115 bool deps( int i ) const { return __left.deps( i ); } \
120 class ADBinaryAdd< ADCst<TYPE>, R> \
123 enum { nvar = R::nvar }; \
125 typedef TYPE value_type_L; \
126 typedef typename R::value_type value_type_R; \
127 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
128 typedef ADCst<TYPE> L; \
133 const L __left; const R& __right; \
136 ADBinaryAdd(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
140 value_type value() const {return __left.value() + __right.value();} \
141 value_type grad( int __i ) const {return __right.grad( __i );} \
142 value_type hessian( int __i, int __j ) const {return __right.hessian( __i, __j);} \
144 bool deps( int i ) const { return __right.deps( i ); } \
147 AD_BIN_ADD_CST(
int )
148 AD_BIN_ADD_CST(
long int )
149 AD_BIN_ADD_CST(
float )
150 AD_BIN_ADD_CST(
double )
151 AD_BIN_ADD_CST(
long double )
153 #undef AD_BIN_ADD_CST
156 template <
class L,
class R>
157 class ADBinarySubtract
160 enum { nvar = L::nvar };
161 typedef typename L::value_type value_type_L;
162 typedef typename R::value_type value_type_R;
163 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type;
166 ADBinarySubtract() {}
172 ADBinarySubtract(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
182 value_type value()
const
184 return __left.value() - __right.value();
186 value_type grad(
int __i )
const
188 return __left.grad( __i ) - __right.grad( __i );
190 value_type
hessian(
int __i,
int __j )
const
192 return __left.hessian( __i, __j ) - __right.hessian( __i, __j );
195 bool deps(
int i )
const
197 return __left.deps( i ) || __right.deps( i );
201 #define AD_BIN_SUB_CST(TYPE) \
203 class ADBinarySubtract<L, ADCst<TYPE> > \
207 enum { nvar = L::nvar }; \
209 typedef typename L::value_type value_type_L; \
210 typedef TYPE value_type_R; \
211 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
212 typedef ADCst<TYPE> R; \
216 ADBinarySubtract() {} \
218 const L& __left; const R __right; \
221 ADBinarySubtract(const L& left, const R & rigth) : __left(left), __right(rigth) {;} \
222 ~ADBinarySubtract() {;} \
225 value_type value() const {return __left.value() - __right.value();} \
226 value_type grad( int __i) const {return __left.grad(__i);} \
227 value_type hessian( int __i, int __j ) const {return __left.hessian( __i, __j);} \
228 bool deps( int i ) const { return __left.deps( i ); } \
233 class ADBinarySubtract< ADCst<TYPE>, R> \
236 enum { nvar = R::nvar }; \
238 typedef TYPE value_type_L; \
239 typedef typename R::value_type value_type_R; \
240 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
241 typedef ADCst<TYPE> L; \
244 ADBinarySubtract() {} \
246 const L __left; const R& __right; \
249 ADBinarySubtract(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
250 ~ADBinarySubtract() {;} \
253 value_type value() const {return __left.value() - __right.value();} \
254 value_type grad(int __i) const {return - __right.grad(__i);} \
255 value_type hessian( int __i, int __j ) const {return - __right.hessian( __i, __j);} \
256 bool deps( int i ) const { return __right.deps( i ); } \
259 AD_BIN_SUB_CST(
int )
260 AD_BIN_SUB_CST(
long int )
261 AD_BIN_SUB_CST(
float )
262 AD_BIN_SUB_CST(
double )
263 AD_BIN_SUB_CST(
long double )
265 #undef AD_BIN_SUB_CST
268 template <
class L,
class R>
269 class ADBinaryMultiply
272 enum { nvar = R::nvar };
273 typedef typename L::value_type value_type_L;
274 typedef typename R::value_type value_type_R;
275 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type;
278 ADBinaryMultiply() {}
284 ADBinaryMultiply(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
293 value_type value()
const
295 return __left.value() * __right.value() ;
297 value_type grad(
int i )
const
299 return __left.grad( i ) * __right.value() + __right.grad( i ) * __left.value();
301 value_type
hessian(
int __i,
int __j )
const
303 return ( __left.hessian( __i, __j )*__right.value() + __left.grad( __i ) * __right.grad( __j ) +
304 __left.grad( __j ) * __right.grad( __i ) + __left.value()*__right.hessian( __i, __j ) );
307 bool deps(
int i )
const
309 return __left.deps( i ) || __right.deps( i );
313 #define AD_BIN_MUL_CST(TYPE) \
315 class ADBinaryMultiply<L, ADCst<TYPE> > \
319 enum { nvar = L::nvar }; \
321 typedef typename L::value_type value_type_L; \
322 typedef TYPE value_type_R; \
323 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
324 typedef ADCst<TYPE> R; \
327 ADBinaryMultiply() {} \
329 const L& __left; const R __right; \
332 ADBinaryMultiply(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
333 ~ADBinaryMultiply() {;} \
335 value_type value() const {return __left.value() * __right.value() ;} \
336 value_type grad(int i) const {return __left.grad(i) * __right.value();} \
337 value_type hessian(int i, int j) const {return __left.hessian(i,j) * __right.value();} \
338 bool deps( int i ) const { return __left.deps( i ); } \
342 class ADBinaryMultiply< ADCst<TYPE>, R> \
346 enum { nvar = R::nvar }; \
348 typedef TYPE value_type_L; \
349 typedef typename R::value_type value_type_R; \
350 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
351 typedef ADCst<TYPE> L; \
354 ADBinaryMultiply() {} \
356 const L __left; const R& __right; \
359 ADBinaryMultiply(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
360 ~ADBinaryMultiply() {;} \
362 value_type value() const {return __left.value() * __right.value() ;} \
363 value_type grad(int i) const {return __right.grad(i) * __left.value();} \
364 value_type hessian(int i, int j) const {return __right.hessian(i,j) * __left.value();} \
365 bool deps( int i ) const { return __right.deps( i ); } \
368 AD_BIN_MUL_CST(
int )
369 AD_BIN_MUL_CST(
long int )
370 AD_BIN_MUL_CST(
float )
371 AD_BIN_MUL_CST(
double )
372 AD_BIN_MUL_CST(
long double )
374 #undef AD_BIN_MUL_CST
377 template <
class L,
class R>
class ADBinaryDivide
380 enum { nvar = R::nvar };
381 typedef typename L::value_type value_type_L;
382 typedef typename R::value_type value_type_R;
383 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type;
392 ADBinaryDivide(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
402 value_type value()
const
404 return __left.value() / __right.value();
406 value_type grad(
int i )
const
408 return ( __left.grad( i ) / __right.value() ) - __right.grad( i ) * __left.value() / ( __right.value() * __right.value() ) ;
411 value_type
hessian(
int __i,
int __j )
const
413 return -( - __left.hessian( __i,__j )*__right.value()*__right.value() +
414 __left.grad( __j )* __right.grad( __i ) * __right.value() +
415 __left.grad( __i )* __right.grad( __j ) * __right.value() -
416 value_type( 2.0 ) * __left.value()* __right.grad( __i ) * __right.grad( __j ) +
417 __left.value() * __right.value() * __right.hessian( __i, __j ) ) / ( __right.value()*__right.value()*__right.value() );
420 bool deps(
int i )
const
422 return __left.deps( i ) || __right.deps( i );
426 #define AD_BIN_DIV_CST(TYPE) \
428 class ADBinaryDivide<L, ADCst<TYPE> > \
432 enum { nvar = L::nvar }; \
434 typedef typename L::value_type value_type_L; \
435 typedef TYPE value_type_R; \
436 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
437 typedef ADCst<TYPE> R; \
440 ADBinaryDivide() {} \
442 const L& __left; const R __right; \
445 ADBinaryDivide(const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
446 ~ADBinaryDivide() {;} \
449 value_type value() const {return __left.value() / __right.value();} \
450 value_type grad(int i) const {return __left.grad(i) / __right.value();} \
451 value_type hessian(int i, int j) const {return __left.hessian(i,j) / __right.value();} \
452 bool deps( int i ) const { return __left.deps( i ); } \
456 class ADBinaryDivide< ADCst<TYPE>, R> \
460 enum { nvar = R::nvar }; \
462 typedef TYPE value_type_L; \
463 typedef typename R::value_type value_type_R; \
464 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
465 typedef ADCst<TYPE> L; \
468 ADBinaryDivide() {} \
470 const L __left; const R& __right; \
473 ADBinaryDivide(L left, const R& right) : __left(left), __right(right) {;} \
474 ~ADBinaryDivide() {;} \
476 value_type value() const {return __left.value() / __right.value();} \
477 value_type grad(int i) const {return (- __right.grad(i) * __left.value() ) / (__right.value() * __right.value()) ;} \
478 value_type hessian(int __i, int __j) const \
479 { return __left.value() * \
480 ( 2 *__right.grad(__i)*__right.grad(__j) - __right.value()*__right.hessian(__i,__j) )/ \
481 std::pow(__right.value(),3.); \
483 bool deps( int i ) const { return __right.deps( i ); } \
486 AD_BIN_DIV_CST(
int )
487 AD_BIN_DIV_CST(
long int )
488 AD_BIN_DIV_CST(
float )
489 AD_BIN_DIV_CST(
double )
490 AD_BIN_DIV_CST(
long double )
492 #undef AD_BIN_DIV_CST
496 template <
class L,
class R>
500 enum { nvar = R::nvar };
501 typedef typename L::value_type value_type_L;
502 typedef typename R::value_type value_type_R;
504 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type;
513 ADBinaryPow(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
523 value_type value()
const
525 return std::pow( __left.value(), __right.value() );
527 value_type grad(
int i )
const
529 return ( __right.grad( i )*std::log( __left.value() )+__right.value()*__left.grad( i )/__left.value() )
530 *std::pow( __left.value(), __right.value() );
533 bool deps(
int i )
const
535 return __left.deps( i ) || __right.deps( i );
541 class ADBinaryPow<L, ADCst<typename L::value_type> >
544 enum { nvar = L::nvar };
545 typedef typename L::value_type value_type;
546 typedef ADCst<value_type> R;
555 ADBinaryPow(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
565 value_type value()
const
567 return std::pow( __left.value(),__right.value() ) ;
569 value_type grad(
int i )
const
571 return ( __right.value()*__left.grad( i )/__left.value() )*std::pow( __left.value(), __right.value() );
573 value_type
hessian(
int i,
int j )
const
577 bool deps(
int i )
const
579 return __left.deps( i );
585 class ADBinaryPow< ADCst<typename R::value_type>, R>
588 enum { nvar = R::nvar };
589 typedef typename R::value_type value_type;
590 typedef ADCst<value_type> L;
599 ADBinaryPow(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
608 const value_type value()
const
610 return std::pow( __left.value(),__right.value() );
612 value_type grad(
int i )
const
614 return ( __right.grad( i )*std::log( __left.value() ) )*std::pow( __left.value(), __right.value() );
617 value_type
hessian(
int i,
int j )
const
619 return std::pow( __left.value(),__right.value()-2.0 )*__right.value()*__right.value()*__left.grad( i )*__left.grad( j ) +
620 std::pow( __left.value(),__right.value()-1.0 )*__right.value()*__left.hessian( i,j ) -
621 std::pow( __left.value(),__right.value()-2.0 )*__right.value()*__left.grad( i )*__left.grad( j );
623 bool deps(
int i )
const
625 return __right.deps( i );
630 class ADBinaryPow< L , ADCst<int> >
633 enum { nvar = L::nvar };
635 typedef typename L::value_type value_type;
636 typedef ADCst<int> R;
645 ADBinaryPow(
const L& left,
const R& rigth ) : __left( left ), __right( rigth )
654 template<
int isFundamental,
typename L_,
typename R_>
657 typedef typename L_::value_type value_type;
658 static value_type value( L_
const& __left, R_
const& __right )
660 return pow( __left.value(),__right.value() );
662 static value_type grad( L_
const& __left, R_
const& __right,
int __i )
664 return value_type( __right.value() )*pow( __left.value(), __right.value()-1 );
666 static value_type
hessian( L_
const& __left, R_
const& __right,
int i,
int j )
668 return pow( __left.value(),__right.value()-2.0 )*__right.value()*__right.value()*__left.grad( i )*__left.grad( j ) +
669 pow( __left.value(),__right.value()-1.0 )*__right.value()*__left.hessian( i,j ) -
670 pow( __left.value(),__right.value()-2.0 )*__right.value()*__left.grad( i )*__left.grad( j );
673 template<
typename L_,
typename R_>
674 struct Value<1, L_, R_>
676 typedef typename L_::value_type value_type;
677 static value_type value( L_
const& __left, R_
const& __right )
679 return std::pow( __left.value(),__right.value() );
681 static value_type grad( L_
const& __left, R_
const& __right,
int __i )
683 return __right.value()*std::pow( __left.value(), __right.value()-1 );
685 static value_type
hessian( L_
const& __left, R_
const& __right,
int i,
int j )
687 return std::pow( __left.value(),__right.value()-2.0 )*__right.value()*__right.value()*__left.grad( i )*__left.grad( j ) +
688 std::pow( __left.value(),__right.value()-1.0 )*__right.value()*__left.hessian( i,j ) -
689 std::pow( __left.value(),__right.value()-2.0 )*__right.value()*__left.grad( i )*__left.grad( j );
692 value_type value()
const
694 return Value<
true,L,R>::value( __left, __right );
696 value_type grad(
int i )
const
698 return Value<
true,L,R>::grad( __left, __right, i );
700 value_type
hessian(
int i,
int j )
const
702 return Value<
true,L,R>
::hessian( __left, __right, i, j );;
704 bool deps(
int i )
const
706 return __left.deps( i );
712 #define AD_BIN_REL_CST(Rel, OP,TYPE) \
714 class ADBinary ##Rel <L, ADCst<TYPE> > \
718 enum { nvar = L::nvar }; \
720 typedef typename L::value_type value_type_L; \
721 typedef TYPE value_type_R; \
722 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
723 typedef ADCst<TYPE> R; \
726 ADBinary ##Rel () {} \
728 const L& __left; const R __right; \
731 ADBinary ##Rel (const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
732 ~ADBinary ##Rel () {;} \
735 value_type value() const { return __left.value() OP __right.value(); } \
736 value_type grad(int i) const { return __left.value() OP __right.value(); } \
737 value_type hessian(int i, int j) const { return __left.value() OP __right.value(); } \
738 bool deps( int i ) const { return __left.deps( i ); } \
742 class ADBinary ##Rel < ADCst<TYPE>, R> \
746 enum { nvar = R::nvar }; \
748 typedef TYPE value_type_L; \
749 typedef typename R::value_type value_type_R; \
750 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
751 typedef ADCst<TYPE> L; \
754 ADBinary ##Rel () {} \
756 const L __left; const R& __right; \
759 ADBinary ##Rel (L left, const R& right) : __left(left), __right(right) {;} \
760 ~ADBinary ##Rel () {;} \
762 value_type value() const { return __left.value() OP __right.value(); } \
763 value_type grad(int i) const { return __left.value() OP __right.value(); } \
764 value_type hessian(int i, int j) const { return __left.value() OP __right.value(); } \
765 bool deps( int i ) const { return __right.deps( i ); } \
768 #define AD_BIN_REL( Rel, OP ) \
769 template <class L, class R> \
770 class ADBinary ##Rel \
773 enum { nvar = R::nvar }; \
774 typedef typename L::value_type value_type_L; \
775 typedef typename R::value_type value_type_R; \
777 typedef typename SNumericalTraits<value_type_L,value_type_R>::promote value_type; \
780 ADBinary ##Rel () {} \
782 const L& __left; const R& __right; \
785 ADBinary ##Rel (const L& left, const R& rigth) : __left(left), __right(rigth) {;} \
786 ~ADBinary ##Rel () {;} \
789 value_type value() const {return __left.value() OP __right.value();} \
790 value_type grad(int i) const { return __left.value() OP __right.value(); } \
791 value_type hessian(int i, int j) const { return __left.value() OP __right.value(); } \
793 bool deps( int i ) const { return __left.deps( i ) || __right.deps( i ); } \
795 AD_BIN_REL_CST( Rel, OP, int) \
796 AD_BIN_REL_CST( Rel, OP, long int) \
797 AD_BIN_REL_CST( Rel, OP, float) \
798 AD_BIN_REL_CST( Rel, OP, double) \
799 AD_BIN_REL_CST( Rel, OP, long double)
801 AD_BIN_REL( Greater, > )
802 AD_BIN_REL( Less, < )
803 AD_BIN_REL( GreaterOrEqual, >= )
804 AD_BIN_REL( LessOrEqual, <= )
805 AD_BIN_REL( Equal, == )
806 AD_BIN_REL( NotEqual, != )
809 #undef AD_BIN_REL_CST